using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using HTCoreServiceApp.Common;
using HTCoreServiceApp.DriverInterface;
using HTCoreServiceApp.Models;
using Microsoft.Extensions.Logging;
using HTCoreServiceApp.Communicate;
using System.Text.RegularExpressions;
using System.Security.Cryptography.X509Certificates;
using System.Diagnostics.CodeAnalysis;
using SqlSugar;

namespace HTCoreServiceApp
{
    public class DriverThread : IDisposable
    {
        public readonly MetaDriver MetaDriver;
        public readonly List<MetaGroup> metaGroups;
        public readonly List<MetaTag> metaTagColls;
        public readonly string driverName;
        public IDriverEntity DriverEntity;
        private readonly ILogger logger;
        private Task? _task;
        private readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
        private readonly object _lock = new();
		public DriverThread(MetaDriver metaDriver) 
        {

            MetaDriver= metaDriver;
			//string ConnectionStrings = AESKeyEncrypt.DecryptDES(ConfigHelper.ReadAppSettings("ConnectionStrings", "SqlServer"));
			var db = new SqlSugarClient(StaticLibrary.DBConfig);
			var argument =db.Queryable<Argument>().Where(x => x.DriverId == MetaDriver.DriverId).ToList(); //db.Arguments.Where(x => x.DriverId == MetaDriver.DriverId).ToList(); ;
			if (argument.Count <1)
            {
                Console.WriteLine($"找不到该设备参数:{MetaDriver.DriverName}");
                LogHelper.LogWrite($"找不到该设备参数:{MetaDriver.DriverName}");
                return;
            }

            metaGroups = db.Queryable<MetaGroup>().Where(x => x.DriverId == metaDriver.DriverId).ToList();// db.MetaGroups.Where(x => x.DriverId == metaDriver.DriverId).ToList() ;


            metaTagColls = db.Queryable<MetaTag>().ToList(); //db.MetaTags.ToList();
            var groupMetaTags = EFLinqExtenHelper.GetGroupMetaTags(metaTagColls, metaGroups.Select(x => x.GroupId).ToArray());
            driverName = db.Queryable<MetaDriver>().Where(x => x.DriverId == MetaDriver.DriverId).First().DriverName; //db.MetaDrivers.Where(x => x.DriverId == MetaDriver.DriverId).First().DriverName;

			TagGroup tagGroup = new TagGroup() {
                
                Tags = groupMetaTags,
                Arguments = argument,
                Groups = metaGroups,
                DriverName= driverName,
            };

			//var groups = metaGroups.GroupBy(x => new { x.GroupId });
			//foreach (var metaGroup in groups)
			//{
			//    //if 添加连续或单变量读取标记
			//    tagGroup.SplitTags.Add(metaTags.Where(x => x.GroupId == metaGroup.Key.GroupId).ToList());
			//}
			/**
             * 一、
             * 二、
             * 1、由于sql单表最大字段支持1024个字段，曲工根据变量块拆分存储表，变量Tag添加表名标记，读取完成后根据表明拆分存储语句，分表存储。
             * 2、分表后存储语句增加，解决单次执行单表语句变慢的问题，汇总sql并进行单命令句多表存储。
             * 三、
             * 1、优化数据库访问框架的模式，从单例模式更改为程序上下文实例模式，解决存储命令过多造成sql占用导致数据库连接出错和内存消耗增加的问题。
             * 2、采集服务进行编译时，针对Windows x64平台进行运行优化，避免搭载linux、arm等操作系统的环境导致编译和运行效率低下问题。
             * 四、添加组触发读取事件，在原有自动循环读取的基础上抛出可触发事件类型，激活事件完成一次读取。
             * 五、测试触发事件的
             **/
			/**
             *一、
             *1、
             *2、PLC设定参数修改触发
             *二、
             *1、
             *2、在采集服务原有整型、浮点等数据类型的基础上添加特殊数据类型IFLOAT，用以表示该变量为单字整型储存的浮点数。
             *3、添加小数位数字段，用来储存单字int转浮点时需要移动的小数位数。
             *三、
             *1、在采集服务的连续地址范围添加特殊浮点的字节占用处理。
             *2、采集后的字节数据处理功能中添加整型转浮点处理方式，按照小数位字段的位数将整型还原回浮点。
             *四、
             *1、变量组的Group数据表中增加组类型字段，用来表示该变量组是实时数据组还是设定参数组。
             *2、数据类型添加特俗的BOOL类型，用来表示实时数据的变量组中的设定值变化“订阅”功能，该值为真时读取该设备的设定参数组。
             *五、
             *1、再触发读取设定参数组完成后，采集服务将CPU中的“订阅”BOOL变量复位(复位失败时，“订阅”变量仍为真，下个实时数据读取周期仍会进行设定参数的读取并再次尝试复位)。
             *2、测试
             **/
			/**
             * 一、
             * 1、根据粤北测试的需求，挑选实施计算机配置。
             * 2、制粉全变量趋势chart添加固定对比颜色列表，取消生成不易分辨的随即色数组。
             * 3、制粉全变量趋势功能代码复用至喷煤全变量趋势。
             * 4、喷煤chart轴线只保留主轴线，刻度数字移至主轴左侧。
             * 二、
             * 1、管理系统项目源码中的所有实体类统一添加ID属性标记，标识属于哪个数据库。
             * 2、管理系统使用的ORM框架启用多数据库模式，添加ORM手动切换数据库功能。
             * 三、
             * 1、ORM框架添加自动切换数据库功能，根据实体类代码中的数据库ID，将使用该实体类的查询代码自动切换至对应数据库。
             * 2、拆分管理系统数据库，ETL历史数据、HT模板表等保留作为数据从库。SYS等管理系统框架构建表迁移至新数据库，用作每个喷煤或制粉实例的主库。
             * 3、统一修改管理系统的数据服务类，将所有数据库查询函数代码手动切换为数据从库，普通CURD操作根据标记自动选择对应数据库。
             * 四、
             * 1、修改仿真程序，每秒执行一次曲工仿真函数，将所有数据构建为字节数据写入CPU。
             * 2、本机部署仿真程序，开启原有制粉和喷煤仿真。
             * 3、整理港陆技术方案管理系统软件清单。
             * 五、
             * 1、测试管理系统实例拆分功能，配置多个主库对应一个数据从库程序，通知开启喷煤、制粉实列。
             * 2、配置喷煤和制粉各自的用户、权限、系统菜单显示内同容。
             **/
			//DriverEntity = CommunicationAdapter.GetAdapter(tagGroup);
			Task.Run(() =>
            {
                DriverEntity = CommunicationAdapter.GetAdapter(tagGroup);
            });
            //DriverEntity = CommunicationAdapter.GetAdapter(argument, metaGroups, metaTags);

            //DriverEntity = new DriverEntity()
            //{
            //    DeviceId = argument[0].DriverId.ToString(),
            //    IsConnected = false,
            //    Timeout = int.Parse(argument[3])
            //};
            //logger.LogInformation($"线程已启动:{MetaDriver.DriverName}");
            Thread.Sleep(1000);
            _task = Task.Run(() =>
            {
                while (true)
                {
                    if (_tokenSource.IsCancellationRequested)
                    {
                        //logger.LogInformation($"停止线程:{MetaDriver.DriverName}");
                        return;
                    }
                    lock (_lock)
                    {
                        try
                        {
                            if (DriverEntity.IsConnected)
                            {

                            }
                            else
                            {
                                
                            }
                        }
                        catch(Exception ex) 
                        {

                        }
                    }
                    Thread.Sleep(1000);
                }
            });

            
        }

        public int DriverWrite(string para)
		{
			return DriverEntity.Write(para);
		}

		public void StopThread()
        {

        }
        public void Dispose()
        {
            throw new NotImplementedException();
        }
    }
}
