using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using InTheHand.Net.Sockets;
using InTheHand.Net;
using ATUtil.Diagnostics;
using InTheHand.Net.Bluetooth;

namespace AT288Demo.Net.Dialog
{
    public partial class BluetoothScanDeviceDialog : Form
    {
        #region Declare Deleagetor
        private delegate void AddDeviceInvokeHanalder(BluetoothDeviceInfo device);
        private delegate void DiscoverDevicesCompleteInvokeHanalder();
        #endregion

        #region Declare Constant
        private const string DEVICE_NAME = "AT288";
        private const int MAX_DEVICE = 32;
        #endregion

        #region Member Variable
        private AddDeviceInvokeHanalder m_fnAddDevice;
        private DiscoverDevicesCompleteInvokeHanalder m_fnDiscoverDeviceComplete;

        private BluetoothAddress m_Address;
        private ListViewGroup grpPaired;
        private ListViewGroup grpPairing;
        private ListViewGroup m_CurrentGroup;
        #endregion

        #region Constructor
        public BluetoothScanDeviceDialog()
        {
            InitializeComponent();

            grpPaired = new ListViewGroup("Paired Devices", HorizontalAlignment.Left);
            grpPaired.Header = "Paired Devices";
            grpPaired.Name = "grpPaired";
            grpPairing = new ListViewGroup("Pairing Enabled Devices", HorizontalAlignment.Left);
            grpPairing.Header = "Pairing Enabled Devices";
            grpPairing.Name = "grpPairing";
            lstDevices.Groups.AddRange(new ListViewGroup[] { grpPaired, grpPairing });
            m_CurrentGroup = grpPaired;

            m_fnAddDevice = new AddDeviceInvokeHanalder(AddDevice);
            m_fnDiscoverDeviceComplete = new DiscoverDevicesCompleteInvokeHanalder(DiscoverDevicesComplete);

            m_Address = null;
        }
        #endregion

        #region Properties
        public string Address { get { return m_Address.ToString(); } }
        #endregion

        #region Event Handler
        private void BluetoothScanDeviceDialog_Load(object sender, EventArgs e)
        {
            ctlBluetooth.DiscoverDevicesAsync(MAX_DEVICE, true, true, false, false, null);
        }

        private void BluetoothScanDeviceDialog_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (DialogResult != DialogResult.OK)
                DialogResult = DialogResult.Cancel;
        }

        private void lstDevices_DoubleClick(object sender, EventArgs e)
        {
            SelectedDevice();
        }

        private void lstDevices_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
                SelectedDevice();
        }

        private void btnScan_Click(object sender, EventArgs e)
        {
            picWaitProgress.Visible = true;
            btnScan.Enabled = false;

            ctlBluetooth.DiscoverDevicesAsync(MAX_DEVICE, false, false, true, true, null);
        }
        #endregion

        #region Bluetooth Event Handler
        private void ctlBluetooth_DiscoverDevicesProgress(object sender, DiscoverDevicesEventArgs e)
        {
            //ATrace.WriteLine("EVENT. ctlBluetooth_DiscoverDevicesProgress({0})", e.Cancelled);
            FindDevice(e.Devices);
        }

        private void ctlBluetooth_DiscoverDevicesComplete(object sender, DiscoverDevicesEventArgs e)
        {
            //ATrace.WriteLine("EVENT. ctlBluetooth_DiscoverDevicesComplete({0})", e.Cancelled);
            FindDevice(e.Devices);
            DiscoverDevicesComplete();
        }
        #endregion

        #region Inner Methods
        private void FindDevice(BluetoothDeviceInfo[] devices)
        {
            foreach (BluetoothDeviceInfo device in devices)
            {
                ATrace.WriteLine("@@@@ DEBUG. Scan Paired Device {{{0}, {1}, {2}, {3}, {4}}}",
                    device.DeviceName, device.DeviceAddress,
                    device.Connected, device.ClassOfDevice.Device,
                    device.ClassOfDevice.MajorDevice);

                if (device.DeviceName.Contains(DEVICE_NAME) &&
                    device.Connected == false &&
                    device.ClassOfDevice.Device == DeviceClass.Uncategorized &&
                    device.ClassOfDevice.MajorDevice == DeviceClass.Uncategorized)
                {
                    AddDevice(device);
                }
            }
        }

        private void AddDevice(BluetoothDeviceInfo device)
        {
            if (InvokeRequired)
            {
                Invoke(m_fnAddDevice, (object)device);
                return;
            }

            foreach (ListViewItem item in lstDevices.Items)
            {
                if (item.SubItems[1].Text.Equals(device.DeviceAddress.ToString("C")))
                {
                    return;
                }
            }

            ListViewItem newItem = new ListViewItem(new string[] { 
                        device.DeviceName, 
                        device.DeviceAddress.ToString("C")
                    });
            newItem.Group = m_CurrentGroup;
            newItem.ImageIndex = 0;
            newItem.Tag = device;
            lstDevices.Items.Add(newItem);
        }

        private void DiscoverDevicesComplete()
        {
            if (InvokeRequired)
            {
                Invoke(m_fnDiscoverDeviceComplete);
                return;
            }

            if (m_CurrentGroup == grpPaired)
            {
                m_CurrentGroup = grpPairing;
            }

            picWaitProgress.Visible = false;
            lstDevices.Enabled = btnScan.Enabled = true;
        }

        private void SelectedDevice()
        {
            picWaitProgress.Visible = false;

            if (lstDevices.SelectedItems.Count <= 0) return;

            ListViewItem item = lstDevices.SelectedItems[0];
            BluetoothDeviceInfo device = (BluetoothDeviceInfo)item.Tag;

            if (device.Authenticated == false)
            {
                BluetoothInputPinCodeDialog dlg = new BluetoothInputPinCodeDialog();
                if (dlg.ShowDialog(this) != DialogResult.OK)
                    return;

                picWaitProgress.Visible = true;

                if (!BluetoothSecurity.PairRequest(device.DeviceAddress, dlg.PinCode))
                {
                    ATrace.WriteLine("ERROR. Failed to pair request {{{0} : {1}}}",
                        device.DeviceAddress.ToString("C"), dlg.PinCode);
                    return;
                }
                picWaitProgress.Visible = true;
            }
            m_Address = device.DeviceAddress;
            DialogResult = DialogResult.OK;
            Close();
        }
        #endregion
    }
}
