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

using System.Collections.Generic;
using System.Threading;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;

using Wayne.FDCPOSInterface.Configuration;
using Wayne.FDCPOSLibrary;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

namespace Wayne.FDCPOSInterface
{
    public abstract class FDCPOSManager
    {
        //[ComVisible(false)]
        //public static SINPFileTrace tracer = null;

        public Dictionary<string, FDCPOSClient> fdcClientList;

        [ComVisible(false)]
        public static long messageIdCounter = 1;

        [ComVisible(false)]
        public bool encryptedHeader;

        [ComVisible(false)]
        public string forecourtConfiguration;

        [ComVisible(false)]
        public bool useExtensions;

        [ComVisible(false)]
        public string certificate;

        public FDCPOSManager()
        {
            encryptedHeader = false;
            fdcClientList = new Dictionary<string, FDCPOSClient>();
            forecourtConfiguration = "";
            FDCGlobal.ProtocolVersion = FDCVersion.V0003;
            useExtensions = true;
            certificate = certificateType.NONE;
        }

        public abstract void DisconnectClient(FDCPOSClient fdcposClient);

    }

    public class FDCPOSInterfaceServerManager : FDCPOSManager
    {
        //protected static NLog.Logger fdcSocketLogger = NLog.LogManager.LoadConfiguration("nlog.config").GetLogger("FdcServerSocket");
        protected ILogger fdcSocketLogger;
        //= ServiceBuilder.Provider
        //.GetRequiredService<ILoggerFactory>().CreateLogger("FdcServerSocket");
        public static string FDCPOSServerApplication = "FDCPOSServer@@@";
        public static FDCPOSManager fdcPosManager;
        public FDCPOSInterfaceServer fdcPosInterface;

        private TcpListener _socketChannelA = null;
        [ComVisible(false)]
        public TcpListener socketChannelA
        {
            get { return _socketChannelA; }
            set { _socketChannelA = value; }
        }

        [ComVisible(false)]
        public FdcServerTcpHandler FdcServerTcpHandler;


        public FDCPOSInterfaceServerManager(IServiceProvider services)
            : base()
        {
            var loggerFactory = services.GetRequiredService<ILoggerFactory>();
            this.fdcSocketLogger = loggerFactory.CreateLogger("DynamicPrivate_FdcServerSocket");
        }

        public override void DisconnectClient(FDCPOSClient fdcPosClient)
        {
            string fdcClientId = FDCPOSClient.getClientID(fdcPosClient.workstationID, fdcPosClient.applicationSender);

            try
            {
                fdcSocketLogger.LogDebug("     Removing Client: " + fdcClientId + " from client list");
                try
                {
                    fdcPosInterface.messages.RemovePendingMessages(fdcClientId);
                }
                finally
                {
                    fdcPosClient.heartbeat?.Dispose();
                    fdcClientList.Remove(fdcClientId);
                    fdcPosManager.fdcClientList.Remove(fdcClientId);
                    fdcPosInterface.Disconnect(fdcPosClient.workstationID, fdcPosClient.applicationSender);
                    fdcSocketLogger.LogDebug("          removed Client: " + fdcClientId);
                }
            }
            catch (Exception e)
            {
                fdcSocketLogger.LogError("     Removing Client: " + fdcClientId + " exceptioned: " + e);
            }
        }
    }


    public class FDCPOSConfigurationManager : FDCPOSManager
    {
        public static FDCPOSConfigurationManager fdcposManager = null;

        public ConfigurationInterface configurationInterface;

        private TcpListener _socketChannelConfig = null;
        [ComVisible(false)]
        public TcpListener socketChannelConfig
        {
            get { return _socketChannelConfig; }
            set { _socketChannelConfig = value; }
        }

        [ComVisible(false)]
        public FdcServerTcpHandler respChannelConfigThreadObj;


        public FDCPOSConfigurationManager()
            : base()
        {

        }

        public override void DisconnectClient(FDCPOSClient fdcposClient)
        {

        }
    }
}