using System;
using System.Collections.Generic;
using System.ComponentModel;
using CareFusion.Mosaic.Interfaces.Components;
using CareFusion.Mosaic.Interfaces.Connectors;
using CareFusion.Mosaic.Interfaces.Types.Components;

namespace CareFusion.Mosaic.Connectors.Tcp
{
    /// <summary>
    /// Class which represents the configuration of a TCP inbound connector.
    /// </summary>
    public class TcpInConnectorConfiguration : IComponentConfiguration
    {
        #region Properties

        [Category("TCP Listener Settings")]
        [DisplayName("Listening Port")]
        [Description("The TCP listening port.")]
        public ushort Port
        {
            get;
            set;
        }

        [Category("TCP Listener Settings")]
        [DisplayName("Connection Category")]
        [Description("Defines the category of the connections which are created by this connector.")]
        public ConnectionCategory Category
        {
            get;
            set;
        }

        [Category("TCP Listener Settings")]
        [DisplayName("Maximum Concurrent Connections")]
        [Description("The maximum number of allowed incoming concurrent connections.")]
        public int MaxConcurrentConnections
        {
            get;
            set;
        }

        [Category("Connection Settings")]
        [DisplayName("Read Timeout (s)")]
        [Description("The timeout for read operations in seconds. (0) means no timeout.")]
        public uint ReadTimeout
        {
            get;
            set;
        }

        [Category("Connection Settings")]
        [DisplayName("Write Timeout (s)")]
        [Description("The timeout for write operations in seconds. (0) means no timeout.")]
        public uint WriteTimeout
        {
            get;
            set;
        }

        [Category("TLS/mTLS Settings")]
        [DisplayName("Enable Encyption")]
        [Description("Enable TLS/mTLS encryption")]
        public bool TlsEnable
        {
            get;
            set;
        }

        [Category("TLS/mTLS Settings")]
        [DisplayName("Client Certificate Is Required")]
        [Description("The client is required to provide a certificat to authenticate")]
        public bool ClientCertificateRequired
        {
            get;
            set;
        }
        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="TcpInConnectorConfiguration"/> class.
        /// </summary>
        public TcpInConnectorConfiguration()
        {
            SetDefaultValues();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TcpInConnectorConfiguration"/> class.
        /// </summary>
        /// <param name="configurationValueList">The configuration values to use for initialization.</param>
        public TcpInConnectorConfiguration(List<ConfigurationValue> configurationValueList)
        {
            Initialize(configurationValueList);
        }

        /// <summary>
        /// (Re)Initializes the configuration object with the specified configuration values.
        /// </summary>
        /// <param name="configurationValueList">The configuration values to use for initialization.</param>
        public void Initialize(List<ConfigurationValue> configurationValueList)
        {
            SetDefaultValues();

            foreach (var configValue in configurationValueList)
            {
                if (configValue.Name == "Port")
                {
                    Port = ushort.Parse(configValue.Value);
                }
                else if (configValue.Name == "Category")
                {
                    if (Enum.TryParse<ConnectionCategory>(configValue.Value, out ConnectionCategory category))
                    {
                        Category = category;
                    }
                    else
                    {
                        Category = ConnectionCategory.ItSystem;
                    }
                }
                else if (configValue.Name == "ReadTimeout")
                {
                    ReadTimeout = uint.Parse(configValue.Value);
                }
                else if (configValue.Name == "WriteTimeout")
                {
                    WriteTimeout = uint.Parse(configValue.Value);
                }
                else if (configValue.Name == "MaxConcurrentConnections")
                {
                    MaxConcurrentConnections = int.Parse(configValue.Value);
                }
                else if (configValue.Name == "TlsEnable")
                {
                    TlsEnable = bool.Parse(configValue.Value);
                }
                else if (configValue.Name == "ClientCertificateRequired")
                {
                    ClientCertificateRequired = bool.Parse(configValue.Value);
                }
            }
        }

        /// <summary>
        /// Converts the configuration object into a list of configuration value instances.
        /// </summary>
        /// <returns>
        /// The list of configuration value instances.
        /// </returns>
        public List<ConfigurationValue> ToConfigurationValueList()
        {
            List<ConfigurationValue> resultList = new List<ConfigurationValue>
            {
                new ConfigurationValue() { Name = "Port", Value = Port.ToString() },
                new ConfigurationValue() { Name = "Category", Value = Category.ToString() },
                new ConfigurationValue() { Name = "ReadTimeout", Value = ReadTimeout.ToString() },
                new ConfigurationValue() { Name = "WriteTimeout", Value = WriteTimeout.ToString() },
                new ConfigurationValue() { Name = "MaxConcurrentConnections", Value = MaxConcurrentConnections.ToString() },
                new ConfigurationValue() { Name = "TlsEnable", Value = TlsEnable.ToString() },
                new ConfigurationValue() { Name = "ClientCertificateRequired", Value = ClientCertificateRequired.ToString() }
            };

            return resultList;
        }

        /// <summary>
        /// (Re)Sets the configuration properties to the default values.
        /// </summary>
        private void SetDefaultValues()
        {
            Port = 6050;
            Category = ConnectionCategory.ItSystem;
            MaxConcurrentConnections = 10;
            TlsEnable = false;
            ClientCertificateRequired = false;
        }
    }
}
