using Unosquare.RaspberryIO;
using Unosquare.RaspberryIO.Abstractions;
using Unosquare.WiringPi;

namespace RaspiControl {
    public class Joystick {

        private static readonly IGpioPin joystickUpPin = Pi.Gpio[BcmPin.Gpio19];
        private static readonly IGpioPin joysticDownPin = Pi.Gpio[BcmPin.Gpio13];
        private static readonly IGpioPin joystickLeftPin = Pi.Gpio[BcmPin.Gpio06];
        private static readonly IGpioPin joystickRightPin = Pi.Gpio[BcmPin.Gpio05];
        private static readonly IGpioPin joystickPushPin = Pi.Gpio[BcmPin.Gpio26];

        private static readonly List<IGpioPin> inputPins = new List<IGpioPin> { joystickUpPin, joysticDownPin,
            joystickLeftPin, joystickRightPin, joystickPushPin };

        #region Properties
        public JoystickButton State {
            get {
                JoystickButton state = JoystickButton.None;
                if (!joystickLeftPin.Read()) state |= JoystickButton.Left;
                if (!joystickRightPin.Read()) state |= JoystickButton.Right;
                if (!joystickUpPin.Read()) state |= JoystickButton.Up;
                if (!joysticDownPin.Read()) state |= JoystickButton.Down;
                if (!joystickPushPin.Read()) state |= JoystickButton.Center;
                return state;
            }
        }
        #endregion

        #region Events
        public event EventHandler<JoystickEventArgs>? JoystickChanged;

        private void OnJoystickChanged(JoystickButton state) {
            Console.WriteLine($"Joystick was pushed: {state}");
            this.JoystickChanged?.Invoke(this, new JoystickEventArgs(state));
        }
        #endregion

        public Joystick() {
            Pi.Init<BootstrapWiringPi>();
            foreach (var pin in inputPins) {
                pin.PinMode = GpioPinDriveMode.Input;
            }

            Thread thread = new Thread(Run);
            thread.IsBackground = true;
            thread.Start();
        }

        private void Run() {
            JoystickButton oldState = State;
            while (true) {
                JoystickButton newState = State;
                if (oldState != newState) {
                    oldState = newState;
                    OnJoystickChanged(newState);
                }
                Thread.Sleep(50);
            }
        }
    }
}
