// Created with MonoDevelop
//
//    Copyright (C) 2010 Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.



using System;
using System.Runtime.Serialization;

using FTD2XX_NET4libusb;


namespace Hiperscan.SGS
{
    public delegate void IdleTaskHandler();
	
	public enum DriverType
	{
		FTDI,
		LibUSB,
		WinUSB,
		None
	}

	public enum DeviceType
	{
		SGS,
		SGSNT,
		NSeries
	}

	[Serializable()]
	public class DeviceInfo : System.Runtime.Serialization.ISerializable
	{
		private uint vendor_id;
		private uint product_id;

		private DeviceType device_type = DeviceType.SGS;
		
		private string manufacturer;
		private string description;
		private string serial;

		private RemoteUSBClient remote_usb;

		public DeviceInfo(string manufacturer, string serial, string description, uint vendor_id, uint product_id, DeviceType device_type)
		{
			this.manufacturer = manufacturer;
			this.serial       = serial;
			this.description  = description;
			this.vendor_id    = vendor_id;
			this.product_id   = product_id;
			this.remote_usb   = null;
			this.device_type  = device_type;
		}
		
		public DeviceInfo(string manufacturer, string serial, uint vendor_id, uint product_id, DeviceType device_type)
			: this(manufacturer, serial, "Microspectrometer", vendor_id, product_id, device_type)
		{
		}

		public DeviceInfo(FTD2XX4libusb.FT_DEVICE_INFO_NODE node)
		{
			this.manufacturer = node.Manufacturer;
			this.description  = node.Description;
			this.serial       = node.SerialNumber;
			this.vendor_id    = node.VendorId;
			this.product_id   = node.ProductId;
			this.remote_usb   = null;
		}
		
		public DeviceInfo(SerializationInfo info, StreamingContext context)
		{
			this.manufacturer = (string)info.GetValue("Manufacturer", typeof(string));
			this.description  = (string)info.GetValue("Description",  typeof(string));
			this.serial       = (string)info.GetValue("Serial",       typeof(string));
			this.vendor_id    = (uint)info.GetValue("VendorId",       typeof(uint));
			this.product_id   = (uint)info.GetValue("ProductId",      typeof(uint));
			this.remote_usb   = null;
		}

		public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
		{
			info.AddValue("Manufacturer", this.manufacturer);
			info.AddValue("Description",  this.description);
			info.AddValue("Serial",       this.serial);
			info.AddValue("VendorId",     this.vendor_id);
			info.AddValue("ProductId",    this.product_id);
		}

		public override string ToString()
		{
			return string.Format("[DeviceInfo: Manufacturer={0}, Description={1}, SerialNumber={2}, VendorId={3}, ProductId={4}, RemoteUsbClient={5}, IsRemote={6}, DeviceType={7}]", Manufacturer, Description, SerialNumber, VendorId, ProductId, RemoteUsbClient, IsRemote, DeviceType);
		}

		public string Manufacturer
		{
			get { return this.manufacturer; }
		}
		
		public string Description
		{
			get { return this.description; }
		}
		
		public string SerialNumber
		{
			get          { return this.serial; }
			internal set { this.serial = value; }
		}
		
		public uint VendorId
		{
			get { return this.vendor_id; }
		}
		
		public uint ProductId
		{
			get { return this.product_id; }
		}
		
		public RemoteUSBClient RemoteUsbClient
		{
			get { return this.remote_usb;  }
			set { this.remote_usb = value; }
		}
		
		public bool IsRemote
		{
			get { return this.remote_usb != null; }
		}

		public DeviceType DeviceType
		{
			get { return this.device_type; }
		}
	}

	public interface IUSB
	{
		uint GetNumberOfDevices();
		DeviceInfo[] GetDeviceList();
		void OpenBySerialNumber(string serial);
		void Close();
		void ResetDevice();
		void SetTimeouts(int read_timeout, int write_timeout);
		void SetTimeouts();
		void SetLatency();
		void Purge();
		
		uint Write(byte[] data);
		uint Read(out byte[] data);
		uint Read(out byte[] data, uint len);
		byte[] ReadBlocking(uint len, int timeout, IdleTaskHandler idle_task);
		
		DriverType DriverType { get; }
	}
}
