using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HTCoreServiceApp.Common;
using HTCoreServiceApp.Models;
using HTCoreServiceApp.Communicate.ModbusTcp;
using System.Collections;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.Reflection;
using HTCoreServiceApp.WebApi;

namespace HTCoreServiceApp.DataHandle
{
    public class DataExtractMB
    {
        public static async void  DataExtractCAsync(List<MetaTag> metaTags, string systenName, string groupName, string driverName, int[] bytes, AddressArg addressArg)
        {
            string res = await DataExtractConsecutive(metaTags, systenName, groupName, driverName, bytes, addressArg);
        }
        public static Task <string> DataExtractConsecutive(List<MetaTag> metaTags, string systenName, string groupName, string driverName, int[] bytes, AddressArg addressArg)
        {
            return Task.Run(() =>
            {
                long hdatetime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
                List<MetaTagValue> listMetaTagValue = new List<MetaTagValue>();
                try
                {
                    //CodingTools.StartTime = DateTime.Now.Millisecond;//de
                    foreach (MetaTag metaTag in metaTags)
                    {
                        short datatype = metaTag.DataType;
                        MetaTagValue metaTagValue = PCAutoCopy(metaTag);
                        switch (datatype)
                        {
                            case (short)DataType.FLOAT:
                                metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes, addressArg);
                                break;
                            case (short)DataType.BOOL:
                                metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes, addressArg);
                                break;
                            case (short)DataType.INT:
                                metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes, addressArg);
                                break;
                            case (short)DataType.WORD:
                                metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes, addressArg);
                                break;
                        }
                        listMetaTagValue.Add(metaTagValue);
                    }
                    //CodingTools.EndTime = DateTime.Now.Millisecond;//de
                    //var timess = (CodingTools.EndTime - CodingTools.StartTime).ToString();
                    //Console.WriteLine($"转换耗时：{timess}");
                    //Console.WriteLine(string.Join(",", (Array)listMetaTagValue.ToArray()) + "字节数据转换完成" + ",数据量：" + listMetaTagValue.Count.ToString());

                    //异步缓存
                    Task.Run(()=>
                        DataLiving.DataLive2CaChe(listMetaTagValue, driverName, groupName)
                    );

                    //异步储存
                    Task.Run(() => 
                        DataStorage.DataSave2DB(listMetaTagValue, systenName, driverName, groupName, hdatetime)
                    );

                    return "0";
                }
                catch (Exception ex)
                {
                    return "1";
                }
            });
        }

        /// <summary>
        /// 父类的value赋值给子类
        /// </summary>
        /// <param name="parent"></param>
        /// <returns></returns>
        private static MetaTagValue PCAutoCopy(MetaTag parent)
        {
            MetaTagValue child = new MetaTagValue();


            var ParentType = typeof(MetaTag);


            var Properties = ParentType.GetProperties();


            foreach (var Propertie in Properties)
            {
                if (Propertie.CanRead && Propertie.CanWrite)
                {
                    Propertie.SetValue(child, Propertie.GetValue(parent, null), null);
                }
            }


            return child;

            //listMetaTagValue.Add(new MetaTagValue()
            //{
            //    TagId = metaTag.TagId,

            //    TagName = metaTag.TagName,

            //    DataType = metaTag.DataType,

            //    DataSize = metaTag.DataSize,

            //    Address = metaTag.Address,

            //    GroupId = metaTag.GroupId,

            //    IsActive = metaTag.IsActive,

            //    Archive = metaTag.Archive,

            //    DefaultValue = metaTag.DefaultValue,

            //    Description = metaTag.Description,

            //    Maximum = metaTag.Maximum,

            //    Minimum = metaTag.Minimum,

            //    Cycle = metaTag.Cycle, 
            //});
        }

        private static string GetVlaue(short dataType, string address, int[] bytes, AddressArg addressArg)
        {
            string val = "";

            string startaddress = Regex.Replace(address, "[a-z]", "", RegexOptions.IgnoreCase);
            int address_dem = 0;
            int address_int = 0;
            if (startaddress.Contains(".") && startaddress.Length > 2)
            {
                try
                {
                    string[] address_arr = startaddress.Split('.');
                    address_int = int.Parse(address_arr[0]) - addressArg.AddressOffset;
                    address_dem = int.Parse(address_arr[1]);
                }
                catch (Exception exp)
                {
                    //logger
                }
            }
            else
            {
                address_int = int.Parse(startaddress) - addressArg.AddressOffset;
            }

            switch (dataType)
            {
                case (short)DataType.FLOAT:
                    return ModbusClient.ConvertRegistersToFloat(new int[] { bytes[address_int] , bytes[address_int + 1] }).ToString();
                case (short)DataType.BOOL:
                    int[] Mask = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200,0x400,0x800,0x1000,0x2000,0x4000,0x8000};
                    if (address_dem < 0) address_dem = 0;
                    if (address_dem > 15) address_dem = 15;
                    return ((bytes[address_int] & Mask[address_dem]) != 0).ToString();
                case (short)DataType.INT:
                    return ModbusClient.ConvertRegistersToInt(new int[] { bytes[address_int]}).ToString();
                //case (short)DataType.WORD:
                //    return ModbusClient.ConvertRegistersToInt(bytes, address_int).ToString();
            }
            return val;
        }
    }
}
