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 FObjBase
{
    /// <summary>
    /// 管理全部 XxxxServiceClient 的连接关系
    /// </summary>
    [JsonObject(MemberSerialization.OptIn)]
    public class FObjServiceClientManager
    {
        NLog.ILogger logger = NLog.LogManager.GetCurrentClassLogger();

        private static FObjServiceClientManager instance = null;
        /// <summary>
        /// 全局管理器
        /// </summary>
        public static FObjServiceClientManager Instance 
        {
            get {
                if (instance == null)
                {
                    instance = new FObjServiceClientManager();
                    instance.Load();
                }
                return instance;
            }
        }
        
        /// <summary>
        /// 连接地址
        /// </summary>
        [JsonProperty]
        public List<ConnAddr> ConnAddrs { get; } = new List<ConnAddr>();
        /// <summary>
        /// 默认地址
        /// </summary>
        List<ConnDefaultAddr> DefaultAddrs { get; } = new List<ConnDefaultAddr>();
        
        /// <summary>
        /// 连接到 另一个Obj系统
        /// </summary>
        /// <param name="connName"></param>
        /// <param name="fObjClient"></param>
        /// <returns></returns>
        public void Connect_to_Another_OBJSys(string connName, FObjServiceClient fObjClient) 
        {
            //找到地址
            var connaddr = ConnAddrs.Find(c => c.ConnName == connName);
            if (connaddr == null)
            {
                string addr = "0.0.0.1:12345";//没有默认值,创建连接到不存在的地址，避免出错
                //没有，那就创建一个
                //查找默认值
                var defaultAddr = DefaultAddrs.Find(c => c.ConnName == connName);
                if (defaultAddr != null)
                    addr = defaultAddr.Addr;
                
                connaddr = new ConnAddr() { ConnName = connName, Addr = addr };

                ConnAddrs.Add(connaddr);
            }
            foreach (var id in fObjClient.GetIDs()) 
            {
                if (!connaddr.ClientIds.Contains(id))
                {
                    connaddr.ClientIds.Add(id);
                    connaddr.Conn = FObjSys.Current.Connect_to_Another_OBJSys(connaddr.ep, id);
                } 
            }
        }
        /// <summary>
        ///  客户端注销时通知
        /// </summary>
        /// <param name="fObjClient"></param>
        public void ObjClientDisponse(FObjServiceClient fObjClient) 
        {
            
            if (string.IsNullOrEmpty(fObjClient.ConnName))
                return;

            var connaddr = ConnAddrs.Find(c => c.ConnName == fObjClient.ConnName);
            connaddr.ClientIds.RemoveAll(id => fObjClient.GetIDs().Contains(id));

        }
        /// <summary>
        /// 重连
        /// </summary>
        /// <param name="connName"></param>
        /// <param name="addr"></param>
        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;
            }
            connaddr.Addr = addr;

            if (connaddr.Conn != null)
            {
                var conn = connaddr.Conn;
                if (!conn.RemoteEP.Equals(connaddr.ep))
                {
                    //断开之前的连接
                    FObjSys.Current.Disconnect_to_Another_OBJSys(conn.RemoteEP, connaddr.ClientIds.ToArray());
                }
            }
            connaddr.Conn = FObjSys.Current.Connect_to_Another_OBJSys(connaddr.ep, connaddr.ClientIds.ToArray());
        }
        

        string filename = "serviceManager.json";
        string file_default_path = "default/serviceManager.default.json";
        void LoadDefault() {
            if (!File.Exists(file_default_path))
                return;
            try
            {
                string json = File.ReadAllText(file_default_path);
                var p = JsonConvert.DeserializeObject<List<ConnDefaultAddr>>(json);
                DefaultAddrs.AddRange(p);
            }
            catch(Exception e)
            {

            }
        }
        /// <summary>
        /// 加载配置
        /// </summary>
        void Load() 
        {
            LoadDefault();
            if (File.Exists(filename)) 
            {
                try
                {
                    string json = File.ReadAllText(filename);
                    JsonConvert.PopulateObject(json, this);
                        
                }
                catch 
                {
                    
                }
            }
        }
        
        /// <summary>
        /// 保存配置
        /// </summary>
        public void Save() 
        {
            try
            {

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

    /// <summary>
    /// 连接地址
    /// </summary>
    [JsonObject(MemberSerialization.OptIn)]
    public class ConnAddr 
    {
        /// <summary>
        /// 连接器名称
        /// </summary>
        [JsonProperty]
        public string ConnName;

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

        /// <summary>
        /// EndPoint
        /// </summary>
        public IPEndPoint ep 
        {
            get {
                return Misc.StringConverter.ToIPEndPoint(Addr);
            }
        }

        /// <summary>
        /// 连接
        /// </summary>
        public TCPCConn Conn;

        /// <summary>
        /// 客户端 服务代理Id
        /// </summary>
        public List<UInt32> ClientIds = new List<UInt32>();
    }

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

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