using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Connection;
using VizConnectC;
using VIZ.Framework.Core;
using System.Web.WebSockets;
using VIZ.Package.Domain;

namespace VIZ.Package.Connection
{
    /// <summary>
    /// Viz终结点管理器
    /// </summary>
    public class VizEndpointManager : IPackageEndpointManager, IDisposable
    {
        /// <summary>
        /// 日志
        /// </summary>
        private static ILog log = LogManager.GetLogger(typeof(VizEndpointManager));

        /// <summary>
        /// VIZ总结点管理器
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="remoteIP">IP地址</param>
        /// <param name="remotePort">端口</param>
        public VizEndpointManager(string key, string remoteIP, int remotePort)
        {
            this.Key = key;
            this.RemoteIP = remoteIP;
            this.RemotePort = remotePort;

            this.vizEnginePool = new VizEnginePool();
            this.vizEnginePool.Connected += VizEnginePool_Connected;
            this.vizEnginePool.Disconnected += VizEnginePool_Disconnected;

            this.vizEnginePool.AddRenderer(remoteIP, remotePort);
        }

        /// <summary>
        /// 键
        /// </summary>
        public string Key { get; private set; }

        /// <summary>
        /// 远端IP
        /// </summary>
        public string RemoteIP { get; private set; }

        /// <summary>
        /// 远端端口
        /// </summary>
        public int RemotePort { get; private set; }

        /// <summary>
        /// 是否处于连接状态
        /// </summary>
        public bool IsConnected { get; private set; }

        /// <summary>
        /// 连接状态改变事件参数
        /// </summary>
        public event EventHandler<ConnectionStateChangedEventArgs> ConnectionStateChanged;

        /// <summary>
        /// VIZ连接
        /// </summary>
        public VizConnection VizConnection { get; internal set; }

        /// <summary>
        /// 引擎连接池
        /// </summary>
        private VizEnginePool vizEnginePool;

        /// <summary>
        /// 连接
        /// </summary>
        public bool Connect()
        {
            return this.vizEnginePool.Connect();
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        public void Disconnect()
        {
            this.vizEnginePool.Disconnect();
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="message">消息</param>
        public void Send(string message)
        {
            this.vizEnginePool.Send(message);

            // 记录日志
            VizCommandLogMessage msg = new VizCommandLogMessage();
            msg.Log = $"[{this.RemoteIP}:{this.RemotePort}] 发送: {message}";

            ApplicationDomainEx.MessageManager.Send(msg);
        }

        /// <summary>
        /// 请求返回
        /// </summary>
        /// <param name="message">消息</param>
        /// <returns>返回值</returns>
        public string Request(string message)
        {
            string result = this.vizEnginePool.Request(message);

            // 记录日志
            VizCommandLogMessage msg = new VizCommandLogMessage();
            msg.Log = $"[{this.RemoteIP}:{this.RemotePort}] 发送: {message} 返回: {result}";

            ApplicationDomainEx.MessageManager.Send(msg);

            return result;
        }

        /// <summary>
        /// 销毁
        /// </summary>
        public void Dispose()
        {
            this.vizEnginePool?.Disconnect();
            this.vizEnginePool?.Dispose();
            this.vizEnginePool = null;
        }

        /// <summary>
        /// 断开连接时触发
        /// </summary>
        private void VizEnginePool_Disconnected(object sender, VizEnginePool.ConnectionEventArgs e)
        {
            this.IsConnected = false;
            this.ConnectionStateChanged?.Invoke(this, new ConnectionStateChangedEventArgs(this, false));
        }

        /// <summary>
        /// 连接时触发
        /// </summary>
        private void VizEnginePool_Connected(object sender, VizEnginePool.ConnectionEventArgs e)
        {
            this.IsConnected = true;
            this.ConnectionStateChanged?.Invoke(this, new ConnectionStateChangedEventArgs(this, true));
        }
    }
}
