using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Enumeration;
using Windows.UI.Xaml;

namespace BlueControl.uwp.ViewModels
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        private const string SURFACE_KEYBOARD_NAME = "Surface Keyboard";
        private readonly BluetoothLEAdvertisementWatcher bleWatcher = new BluetoothLEAdvertisementWatcher();
        private bool control = false;
        public Windows.UI.Core.CoreDispatcher StaDispatcher { get; set; }


        public async Task StaExecuteAsync(Action action)
        {
            if (StaDispatcher != null)
                await StaDispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => action());

        }

        private void CloseApplication(TimeSpan delta)
        {
            var dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Tick += (o, e) => App.Current.Exit();
            dispatcherTimer.Interval = delta;
            dispatcherTimer.Start();
        }

        private void CloseApplication()
        {
            CloseApplication(new TimeSpan(0, 0, 2));
        }


        private void Custom_PairingRequested(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args)
        {

            StaExecuteAsync(() => this.Text = "Pin: " + Environment.NewLine + args.Pin);

            args.Accept(args.Pin);
        }

        public MainPageViewModel()
        {
            this.bleWatcher.Received += async (sender, args) =>
             {
                 try
                 {
                     if (!args.IsConnectable || control == true) return;
                     control = true;
                     var dev = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
                     if (dev.Name == SURFACE_KEYBOARD_NAME && dev.DeviceInformation.Pairing.CanPair)
                     {
                         await StaExecuteAsync(() => this.Text = "trying to pair... ");

                         System.Threading.Thread.Sleep(3000);
                         dev.DeviceInformation.Pairing.Custom.PairingRequested += Custom_PairingRequested;
                         var t = await dev.DeviceInformation.Pairing.Custom.PairAsync(DevicePairingKinds.DisplayPin, DevicePairingProtectionLevel.Encryption);
                         if (t.Status == DevicePairingResultStatus.Paired)
                         {
                             this.bleWatcher.Stop();
                             await StaExecuteAsync(() =>
                             {
                                 this.Text = $"Paired and connected {Environment.NewLine} auto closing in 2 seconds ";
                                 CloseApplication();
                             }
                             );
                         }
                         else
                             await StaExecuteAsync(() => this.Text = t.Status.ToString());
                     }
                 }
                 catch { }
                 control = false;

             };
        }



        private string text;
        public string Text
        {
            get { return text; }
            private set
            {
                text = value;
                if (PropertyChanged != null) PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Text"));
            }
        }

        private bool isconnected;
        public bool IsConnected
        {
            get { return isconnected; }
            private set
            {
                isconnected = value;
                if (PropertyChanged != null) PropertyChanged.Invoke(this, new PropertyChangedEventArgs("IsConnected"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;


        public async Task ReloadAsync()
        {
            this.Text = "Loading...";

            IsConnected =
               (from x in await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelectorFromConnectionStatus(BluetoothConnectionStatus.Connected)) where x.Name == SURFACE_KEYBOARD_NAME select x).Any();

            if (!IsConnected)
            {
                var pairedDevice =
              (from x in await DeviceInformation.FindAllAsync(BluetoothLEDevice.GetDeviceSelectorFromPairingState(true)) where x.Name == SURFACE_KEYBOARD_NAME select x).FirstOrDefault();
                if (pairedDevice != null)
                    await pairedDevice.Pairing.UnpairAsync();
                this.Text = $"....searching keyboard. {Environment.NewLine} Please confirm is in pairing mode";
                this.bleWatcher.Start();
            }
            else
            {
                this.Text = $"Paired and connected {Environment.NewLine} auto closing in 2 seconds ";
                CloseApplication();
            }
        }
    }
}
