using MessagePack;
using Newtonsoft.Json;
using ServiceCenter;
using ServiceCenter.Redis;
using System.Text;
using ServiceCenter.Extensions;
using ServiceCenter.Logs;
using ServiceCenter.SqlSugars;
using SqlSugar;
using WCS.Core;
using WCS.WorkEngineering;

namespace WCS.Service
{
    /// <summary>
    /// 工作服务
    /// </summary>
    public class Worker : BackgroundService
    {
        /// <summary>
        /// 记录器
        /// </summary>
        private readonly ILogger<Worker> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">记录器</param>
        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }

        public static readonly string WcsDlog = "WCSDlog";
        public static readonly string Wcsdb = "WCSDB";

        /// <summary>
        ///  执行
        /// </summary>
        /// <param name="stoppingToken">停止令牌</param>
        /// <returns></returns>
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            if (stoppingToken.IsCancellationRequested)
                return;

            #region 初始化Redis连接

            var redisConnectionStrings = RedisHub.Default.Check("RedisConnectionStrings") ?? throw new Exception("请在Redis中配置RedisConnectionStrings");
            var configs = JsonConvert.DeserializeObject<List<DataBaseConnectionString>>(redisConnectionStrings);
            if (configs != null)
            {
                if (configs.All(v => v.Key != "Monitor")) throw new Exception("请在RedisConnectionStrings中配置监控RedisDB库连接字符串");
            }

            foreach (var redisConnection in configs!)
            {
                RedisHub.CreateContext(redisConnection.ConnectionString, redisConnection.Key);
                switch (redisConnection.Key)
                {
                    case "Monitor":
                        RedisHub.SetMonitorContextType(redisConnection.Key);
                        RedisHub.Monitor.Serialize = obj =>
                        {
                            var bytes = MessagePackSerializer.Serialize(obj);
                            return bytes;
                        };
                        RedisHub.Monitor.DeserializeRaw = (bytes, type) =>
                        {
                            var obj = MessagePackSerializer.Deserialize(type, bytes);
                            return obj;
                        };
                        break;

                    case "DebugRedisUrl":
                        RedisHub.SetDebugContextType(redisConnection.Key);
                        Configs.DebugRedisUrl = redisConnection.ConnectionString;
                        break;

                    case "WMS":
                        RedisHub.SetWMSContextType(redisConnection.Key);
                        break;
                }
            }

            #endregion 初始化Redis连接

            #region 启用日志

            //var logConfigText = RedisHub.Default.Check("LogConfigText") ?? throw new Exception("请在Redis中配置log4net相关内容");
            //var logConfig = JsonConvert.DeserializeObject<LogConfig>(logConfigText);
            //LogHub.SetConfigInfo(logConfig!);

            #endregion 启用日志

            _logger.LogInformation("WCS开始启动");
            Configs.ProtocolProxyBaseType = typeof(ProtocolProxy);
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Configs.StringEncoding = Encoding.UTF8;
            //var warehouseName = RedisHub.Default.Check("WarehouseName") ?? throw new Exception("请在Redis中配置仓库名称");
            //if (string.IsNullOrEmpty(warehouseName)) throw new Exception("请在Redis中配置仓库名称");
            //ServiceHub.SetWarehouseName(warehouseName);

            #region 初始化数据库连接

            InstanceFactory.CustomDbName = "TDengine";
            InstanceFactory.CustomDllName = "SqlSugar.BzTDengineCore";
            InstanceFactory.CustomNamespace = "SqlSugar.BzTDengineCore";

            var dbConnectionStrings = RedisHub.Default.Check("DbConnectionStrings") ?? throw new Exception("请在Redis中配置数据库连接相关内容");
            ServiceHub.DbConnectionStrings = JsonConvert.DeserializeObject<List<DataBaseConnectionString>>(dbConnectionStrings);
            if (ServiceHub.DbConnectionStrings != null)
            {
                //if (ServiceHub.DbConnectionStrings.All(v => v.Key != Wcsdb)) throw new Exception("请在DbConnectionStrings中配置WCS基础数据库连接字符串");
                //if (ServiceHub.DbConnectionStrings.All(v => v.Key == Wcsdb && !v.IsDefault)) throw new Exception("请在DbConnectionStrings中配置WCS基础数据库为默认数据库");
                // if (ServiceHub.DbConnectionStrings.All(v => v.Key != WcsDlog)) throw new Exception("请在DbConnectionStrings中配置WCS日志数据库连接字符串");
            }

            //设置连接信息
            List<ConnectionConfig> connectionConfigs = new List<ConnectionConfig>();
            foreach (var connectionString in ServiceHub.DbConnectionStrings!)
            {
                connectionConfigs.Add(new ConnectionConfig()
                {
                    ConfigId = connectionString.Key,
                    ConnectionString = connectionString.ConnectionString,//连接符字串
                    DbType = connectionString.DbType,//数据库类型
                    IsAutoCloseConnection = true,//不设成true要手动close
                    LanguageType = LanguageType.Chinese,
                    MoreSettings = new ConnMoreSettings()
                    {
                        IsNoReadXmlDescription = true
                    }
                });
            };
            SqlSugarHelper.SetDb(new SqlSugarScope(connectionConfigs));

            ServiceHub.DbConnectionStrings.InitDB();

            #endregion 初始化数据库连接

            #region 初始化设备信息

            WorkStart.InitializeDeviceInfo();

            #endregion 初始化设备信息

            #region 初始化PLC访问器及PLC读取协议

            //创建PLC访问器
            Configs.PLCAccessorCreater = new PLCAccessors.PLCAccessorsCreater();

            try
            {
                #region 唤醒所有的世界

                World.StartAll();

                #endregion 唤醒所有的世界

                _logger.LogInformation("WCS启动成功");
            }
            catch (Exception ex)
            {
                _logger.LogError("WCS启动失败{0}", ex.Message);
            }

            #endregion 初始化PLC访问器及PLC读取协议

            LogHub.init();
        }
    }
}
