// 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.Linq;
using System.Runtime.Serialization;


namespace Hiperscan.SGS.SerialInterface
{

    [Serializable()]
    public class DeviceInfo : System.Runtime.Serialization.ISerializable
    {
        internal const string NO_SERIAL_PORT_NAME = "NoSerialPort";
        internal const string SEARCH_PORT_NAME = "SearchSerialPort";

        public DeviceInfo(string manufacturer, string serial, string description, uint vendor_id, uint product_id)
        {
            this.Manufacturer    = manufacturer;
            this.SerialNumber    = serial;
            this.Description     = description;
            this.VendorId        = vendor_id;
            this.ProductId       = product_id;
            this.RemoteSerialInterfaceClient = null;

            SerialInterfaceConfig usb_config = SerialInterfaceConfigurations.DEFAULT_USB_CONFIGS.SingleOrDefault(c => c.VendorId == vendor_id && c.ProductId == product_id);

            this.DeviceType = usb_config?.DeviceType ?? DeviceType.Unknown;
            this.UsbBackend = usb_config?.Backend ?? SerialInterfaceConfig.BackendType.FT245BL;

            this.SerialPortName = (usb_config?.NeedSerialPort ?? false) ?
                DeviceInfo.SEARCH_PORT_NAME : DeviceInfo.NO_SERIAL_PORT_NAME;
        }

        public DeviceInfo(string manufacturer, string serial, uint vendor_id, uint product_id)
            : this(manufacturer, serial, "Microspectrometer", vendor_id, product_id)
        {
        }

        public DeviceInfo(SerializationInfo info, StreamingContext context)
        {
            this.Manufacturer    = (string)info.GetValue("Manufacturer",   typeof(string));
            this.Description     = (string)info.GetValue("Description",    typeof(string));
            this.SerialNumber    = (string)info.GetValue("Serial",         typeof(string));
            this.VendorId        = (uint)info.GetValue("VendorId",         typeof(uint));
            this.ProductId       = (uint)info.GetValue("ProductId",        typeof(uint));
            this.DeviceType      = (DeviceType)info.GetValue("DeviceType", typeof(DeviceType));
            this.RemoteSerialInterfaceClient = null;
            this.UsbBackend      = (SerialInterfaceConfig.BackendType)(info.GetValue("UsbBackend", typeof(SerialInterfaceConfig.BackendType)) ?? SerialInterfaceConfig.BackendType.FT245BL);

            if (String.IsNullOrEmpty(this.SerialPortName))
                this.SerialPortName = DeviceInfo.NO_SERIAL_PORT_NAME;
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Manufacturer", this.Manufacturer);
            info.AddValue("Description",  this.Description);
            info.AddValue("Serial",       this.SerialNumber);
            info.AddValue("VendorId",     this.VendorId);
            info.AddValue("ProductId",    this.ProductId);
            info.AddValue("DeviceType",   this.DeviceType);
            info.AddValue("UsbBackend",   this.UsbBackend);
        }

        public override string ToString()
        {
            return string.Format("DeviceInfo:\n" +
                                 "\tManufacturer={0}\n" +
                                 "\tDescription={1}\n" +
                                 "\tSerialNumber={2}\n" +
                                 "\tVendorId={3:X4}\n" +
                                 "\tProductId={4:X4}\n" +
                                 "\tRemoteUsbClient={5}\n" +
                                 "\tIsRemote={6}\n" +
                                 "\tDeviceType={7}\n" +
                                 "\tProductNames={8}\n" +
                                 "\tSerialPortName={9}",
                                 this.Manufacturer,
                                 this.Description,
                                 this.SerialNumber,
                                 this.VendorId,
                                 this.ProductId,
                                 this.RemoteSerialInterfaceClient,
                                 this.IsRemote, 
                                 this.DeviceType,
                                 this.ProductNames,
                                 this.SerialPortName);
        }

        public string ProductNames
        {
            get
            {
                return ProductInfo.GetProductNameGroup(this.VendorId, this.ProductId);
            }
        }

        public bool HasSerialPort
        {
            get
            {
                return this.SerialPortName != DeviceInfo.NO_SERIAL_PORT_NAME &&
                           this.SerialPortName != DeviceInfo.NO_SERIAL_PORT_NAME;
            }
        }

        public string Manufacturer { get; }
        public string Description  { get; }
        public string SerialNumber { get; internal set; }
        public uint VendorId       { get; }
        public uint ProductId      { get; }
        public string SerialPortName { get; internal set; } = DeviceInfo.NO_SERIAL_PORT_NAME;

        public RemoteSerialInterfaceClient RemoteSerialInterfaceClient { get; set; }

        public SerialInterfaceConfig.BackendType UsbBackend { get; private set; }

        public bool IsRemote
        {
            get { return this.RemoteSerialInterfaceClient != null; }
        }

        public DeviceType DeviceType { get; } = DeviceType.Sgs1900;
    }
}
