using System;
using System.Collections;
using System.Collections.Generic;

using LibUsbDotNet;
using LibUsbDotNet.Info;
using LibUsbDotNet.Main;
using LibUsbDotNet.WinUsb;
using LibUsbDotNet.Descriptors;
using LibUsbDotNet.DeviceNotify;


namespace USB_Comunication
{
	public class USB_Comm
	{
		public USB_Comm()
		{
			// seznam usb zarizeni
			Devices = new List<USB_Device>();
			OtherDevices = new Dictionary<string, string>();

			// ohlasovani prichozich udalosti z USB zarizeni (pripojeni/odpojeni)
			UsbDeviceNotifier = DeviceNotifier.OpenDeviceNotifier();
			UsbDeviceNotifier.OnDeviceNotify += OnUsbChange;
			
		}

		public List<USB_Device> Devices;
		public Dictionary<string, string> OtherDevices;

		public event EventHandler USBdeviceChanged;
        public event EventHandler USBdeviceClosed;

        // ohlasovani prichozich udalosti z USB zarizeni (pripojeni/odpojeni)
        private static IDeviceNotifier UsbDeviceNotifier;

        // inicializace vsech USB zarizeni
        public void InitUsbDevices()
		{
			foreach (UsbRegistry regDev in UsbDevice.AllDevices)
			{
				if (regDev.Vid == 0x03EB && (regDev.Pid == 0x2065 || regDev.Pid == 0x2066))
				{
					this.Devices.Add(new USB_Device(regDev));
					this.OtherDevices.Add(regDev.SymbolicName, regDev.FullName + " - VID: " + regDev.Vid + ", PID: " + regDev.Pid);
				}
				else
				{
					this.OtherDevices.Add(regDev.SymbolicName, regDev.FullName + " - VID: " + regDev.Vid + ", PID: " + regDev.Pid);
				}
			}

			// vyvolani udalosti zmeny seznamu USB zarizeni
            if(USBdeviceChanged != null)
            {
                USBdeviceChanged(this, null);
            }
		}


		// zmena v USB zarizenich
		private void OnUsbChange(object sender, DeviceNotifyEventArgs e)
		{
			if (e.Device != null)
			{
				if (e.EventType == EventType.DeviceArrival)
				{
					string symName = e.Device.Name.Remove(e.Device.Name.IndexOf('{')).ToLower().Remove(0,8);
					foreach (UsbRegistry regDev in UsbDevice.AllDevices)
					{
						if (regDev.SymbolicName.ToLower().Contains(symName))
						{
							if (regDev.Vid == 0x03EB && (regDev.Pid == 0x2065 || regDev.Pid == 0x2066))
							{
								this.Devices.Add(new USB_Device(regDev));
								this.OtherDevices.Add(regDev.SymbolicName, regDev.FullName + " - VID: " + regDev.Vid + ", PID: " + regDev.Pid);
							}
							else
							{
								this.OtherDevices.Add(regDev.SymbolicName, regDev.FullName + " - VID: " + regDev.Vid + ", PID: " + regDev.Pid);
							}
						}
					}
				}
				else if (e.EventType == EventType.DeviceRemoveComplete)
				{
					string symName = e.Device.Name.Remove(e.Device.Name.IndexOf('{')).ToLower().Remove(0,8);
					string tmpToDel = "";

					foreach (string key in OtherDevices.Keys)
					{
						if (key.ToLower().Contains(symName))
						{
							tmpToDel = key;
						}
					}

					if (tmpToDel != "")
					{
						OtherDevices.Remove(tmpToDel);
					}

					USB_Device tmpToClose = null;
					foreach (USB_Device usedDev in Devices)
					{
						if (usedDev.FullName.ToLower().Contains(symName))
						{
							tmpToClose = usedDev;
						}
					}
					if (tmpToClose != null)
					{
						if (tmpToClose.IsOpen)
						{
							if(USBdeviceClosed != null)
                            {
                                USBdeviceClosed(this, null);
                            }
						}
						Devices.Remove(tmpToClose);
					}
				}
			}


            // vyvolani udalosti zmeny seznamu USB zarizeni
            if (USBdeviceChanged != null)
            {
                USBdeviceChanged(this, null);
            }
        }

	}
}
