using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NightScout.Interfaces;
using Raspberry.IO.GeneralPurpose;
using Raspberry.IO.GeneralPurpose.Behaviors;

namespace NightScout
{
    public class RaspberryPIButtonSource : IRaspberryPiButtonSource, IAlerter
    {
        public event Action<bool> ButtonStateChange;

        protected IGpioConnectionDriver PinDriver;
        protected GpioOutputBinaryPin ButtonLEDPin;
        
        private static readonly object ledLock = new object();

        public RaspberryPIButtonSource(Int32 pinNumber)
            : this(pinNumber, new FileGpioConnectionDriver())
        { }

        public RaspberryPIButtonSource(Int32 pinNumber, IGpioConnectionDriver driver)
        {
            //Attempt to monitor the pin
            //pinConfiguration = ConnectorPin.P1Pin11.Input().Name("Switch");
            //pinConfiguration.Reversed = true;
            //pinConfiguration.OnStatusChanged(PinChangeHandler);


            //if(pinConfiguration == null)
            //    Console.WriteLine("null");
            //PinDriver = new FileGpioConnectionDriver();
            PinDriver = driver;
            //var settings = new GpioConnectionSettings { Driver = pinConnectionDriver };

            Console.WriteLine("Making new GPIO connection");
            //pinConnection = new GpioConnection(settings,pinConfiguration);
            //pinConnectionDriver.Allocate(ProcessorPin.Pin17, PinDirection.Input);
            //var pinDriver = pinConnectionDriver.In(ConnectorPin.P1Pin11);
            var buttonPin = PinDriver.In(ConnectorPin.P1Pin16);
            ButtonLEDPin = PinDriver.Out(ConnectorPin.P1Pin22);

            Task.Factory.StartNew(() =>
            {
                Boolean savedState = false;
                while (true)
                {
                    //Pin 11 is inverse (always high unless button is pressed)
                    Boolean state = !(buttonPin.Read());
                    if (savedState != state)
                    {
                        PinChangeHandler(state);
                        savedState = state;
                    }
                    Thread.Sleep(100);
                }
            });
            //Console.WriteLine("Made");
            //pinConnection.PinStatusChanged += pinConnection_PinStatusChanged;
        }

        private void PinChangeHandler(Boolean state)
        {
            if (ButtonStateChange != null)
                ButtonStateChange(state);
        }


        public void StartAlert()
        {
            lock (ledLock)
            {
                ButtonLEDPin.Write(true);
            }
        }

        public void StartUrgentAlert()
        {
            lock (ledLock)
            {
                ButtonLEDPin.Write(true);
            }
        }

        public void StartStaleDataAlert()
        {
            lock (ledLock)
            {
                ButtonLEDPin.Write(true);
            }
        }

        public void StopAlerts()
        {
            lock (ledLock)
            {
                ButtonLEDPin.Write(false);
            }
        }
    }
}
