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

namespace HTCoreServiceApp.DataHandle
{
    public class DataExtract
    {
        public async void  DataExtractCAsync(List<MetaTag> metaTags, string systenName, string groupName, string driverName, byte[] bytes, AddressArg addressArg, long  hdatetime)
        {
            string res = await DataExtractConsecutive(metaTags, systenName, groupName, driverName, bytes, addressArg, hdatetime);
        }
        public Task <string> DataExtractConsecutive(List<MetaTag> metaTags, string systenName, string groupName, string driverName, byte[] bytes, AddressArg addressArg, long hdatetime)
        {
            return Task.Run(() =>
            {
                Console.WriteLine($"{systenName}_{driverName}_{groupName}开始执行储存和缓存 时间 {hdatetime}XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
                //long hdatetime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
                List<MetaTagValue> listMetaTagValue = new List<MetaTagValue>();
                try
                {
                    var t1 = DateTime.Now;
                    //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;
                            case (short)DataType.IFLOAT:
                                var floatPlaces =(int)metaTag.IFloatPlaces;
                                metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes, addressArg, floatPlaces);
                                break;
                        }
                        listMetaTagValue.Add(metaTagValue);
                    }
                    var t2 = DateTime.Now;
                    var timediff = t2 - t1;
                    Console.WriteLine($"{groupName}S7数据转换耗时：{timediff}");
                    //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());

                    

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

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

                    //Task.WaitAll(new Task[] {task1,task2});

                    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, byte[] bytes, AddressArg addressArg, int IFloatPlaces = 2)
        {
            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 S7.GetRealAt(bytes, address_int).ToString("0.########");
                case (short)DataType.BOOL:
                    return S7.GetBitAt(bytes, address_int,address_dem).ToString();
                case (short)DataType.INT:
                    return S7.GetIntAt(bytes, address_int).ToString();
                case (short)DataType.WORD:
                    return S7.GetWordAt(bytes, address_int).ToString();
                case (short)DataType.IFLOAT:
                    var srcValue = S7.GetIntAt(bytes, address_int);
                    return (srcValue / ((float)Math.Pow(10.0f, IFloatPlaces))).ToString();
            }
            return val;
        }
    }
}
