using FObjBase;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace FLY.OBJComponents.Client
{
    /// <summary>
    /// 管理全部 XxxxServiceClient 的连接关系
    /// </summary>
    [JsonObject(MemberSerialization.OptIn)]
    public class ObjServiceClientManager
    {
        NLog.ILogger logger = NLog.LogManager.GetCurrentClassLogger();

        private static ObjServiceClientManager instance = null;
        public static ObjServiceClientManager Instance 
        {
            get {
                if (instance == null)
                {
                    instance = new ObjServiceClientManager();
                    instance.Load();
                }
                return instance;
            }
        }
        [JsonProperty]
        public List<ConnAddr> ConnAddrs = new List<ConnAddr>();

        [JsonProperty]
        public List<ObjServiceClientInfo> ClientInfos = new List<ObjServiceClientInfo>();

        public UInt32 Connect_to_Another_OBJSys(string connName, string serviceName, FObj fObj) 
        {
            //找到地址
            var connaddr = ConnAddrs.Find(c => c.ConnName == connName);
            if (connaddr == null)
            {
                //没有!!!!,失败!!!
                logger.Error($"{connName}.{serviceName} 需要连接到服务器,但找不到 {connName}");
                return 0;
            }

            //找服务Id
            var clientInfo = ClientInfos.Find(c => c.ConnName == connName && c.ServiceName == serviceName);
            if (clientInfo == null)
            {
                //没有!!!!,失败!!!
                logger.Error($"{connName}.{serviceName} 需要连接到服务器,但找不到 服务Id");
                return 0;
            }
            clientInfo.ClientId = fObj.ID;


            connaddr.conn = FObjSys.Current.Connect_to_Another_OBJSys(connaddr.ep, clientInfo.ClientId);

            return clientInfo.ServiceId;
        }

        public void ReConnect(string connName, string addr) 
        {
            //找到地址
            var connaddr = ConnAddrs.Find(c => c.ConnName == connName);
            if (connaddr == null)
            {
                //没有!!!!,失败!!!
                logger.Error($"ReConnect({connaddr},{addr}), 不能找到 ConnAddr");
                return;
            }

            if (connaddr.conn != null)
            {
                var conn = connaddr.conn;
                if (!conn.RemoteEP.Equals(Misc.StringConverter.ToIPEndPoint(addr)))
                {
                    //断开之前的连接
                    FObjSys.Current.Disconnect_to_Another_OBJSys(conn.RemoteEP, GetAllClientIds(connaddr.ConnName));
                }
            }
            connaddr.conn = FObjSys.Current.Connect_to_Another_OBJSys(connaddr.ep, GetAllClientIds(connaddr.ConnName));
        }
        
        
        UInt32[] GetAllClientIds(string connName) 
        {
            return ClientInfos.FindAll(c => c.ConnName == connName && c.ClientId != 0).Select(c => c.ClientId).ToArray();
        }
        string filename = "serviceManager.json";
        public void Load() 
        {
            if (File.Exists(filename)) 
            {
                try
                {
                    string json = File.ReadAllText(filename);
                    JsonConvert.PopulateObject(json, this);
                    if (this.ConnAddrs == null)
                        this.ConnAddrs = new List<ConnAddr>();
                    if (this.ClientInfos == null)
                        this.ClientInfos = new List<ObjServiceClientInfo>();
                }
                catch 
                {
                    
                }
            }
        }
        public void Save() 
        {
            try
            {

                string json = JsonConvert.SerializeObject(this, Formatting.Indented);
                File.WriteAllText(filename, json);
            }
            catch 
            {
            
            }
        }
    }

    public class ObjServiceClientInfo 
    {
        /// <summary>
        /// 连接器名称
        /// </summary>
        public string ConnName;

        /// <summary>
        /// 服务名称, 客户端 在 unity的名称
        /// </summary>
        public string ServiceName;

        /// <summary>
        /// 服务Id
        /// </summary>
        public UInt32 ServiceId;

        [JsonIgnore]
        public UInt32 ClientId;
    }

    public class ConnAddr 
    {
        /// <summary>
        /// 连接器名称
        /// </summary>
        public string ConnName;

        /// <summary>
        /// 设备地址
        /// </summary>
        public string Addr;

        public IPEndPoint ep 
        {
            get {
                return Misc.StringConverter.ToIPEndPoint(Addr);
            }
        }
        [JsonIgnore]
        public TCPCConn conn;
    }
}