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;
using HTCoreServiceApp.Communicate.AllenBradleyEIP;

namespace HTCoreServiceApp.DataHandle
{
    public class DataExtractAB
    {
        public static async void  DataExtractCAsync(List<MetaTagAB> metaTags, string systenName, string groupName, string driverName, List<ResultListAB> resultLists)
        {
            string res = await DataExtractConsecutive(metaTags, systenName, groupName,  driverName, resultLists);
        }
        public static Task <string> DataExtractConsecutive(List<MetaTagAB> metaTags, string systenName, string groupName, string driverName, List<ResultListAB> resultLists)
        {
            return Task.Run(() =>
            {
                long hdatetime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
                List<MetaTagValue> listMetaTagValue = new List<MetaTagValue>();
                try
                {
                    //CodingTools.StartTime = DateTime.Now.Millisecond;//de
                    foreach (var result in resultLists)
                    {
                        byte[] bytes = new byte[result.Result.SourceBuff.Length - 48];
                        //result.Result.SourceBuff.CopyTo(bytes, 48);
                        Array.Copy(result.Result.SourceBuff, 48, bytes, 0,bytes.Length);
                        foreach (MetaTag metaTag in result.ScanTags)
                        {
                            short datatype = metaTag.DataType;
                            MetaTagValue metaTagValue = PCAutoCopy(metaTag);
                            switch (datatype)
                            {
                                case (short)DataType.FLOAT:
                                    metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes);
                                    break;
                                case (short)DataType.BOOL:
                                    metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes);
                                    break;
                                case (short)DataType.INT:
                                    metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes);
                                    break;
                                case (short)DataType.WORD:
                                    metaTagValue.TagValue = GetVlaue(datatype, metaTag.Address, bytes);
                                    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, byte[] bytes)
        {
            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]) ;
                    address_dem = int.Parse(address_arr[1]);
                }
                catch (Exception exp)
                {
                    //logger
                }
            }
            else
            {
                address_int = int.Parse(startaddress) ;
            }

            switch (dataType)
            {
                case (short)DataType.FLOAT:
                    //return S7.GetRealAt(bytes, address_int).ToString();
                    return BitConverter.ToSingle(new byte[] { bytes[address_int], bytes[address_int + 1], bytes[address_int + 2], bytes[address_int + 3] }, 0).ToString();
                case (short)DataType.BOOL:
                    //return S7.GetBitAt(bytes, address_int,address_dem).ToString();
                    byte[] Mask = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
                    if (address_dem < 0) address_dem = 0;
                    if (address_dem > 7) address_dem = 7;
                    return ((bytes[address_int] & Mask[address_dem]) != 0).ToString();
                case (short)DataType.INT:
                    return S7.GetIntAt(bytes, address_int).ToString();
                case (short)DataType.WORD:
                    return S7.GetWordAt(bytes, address_int).ToString();
            }
            return val;
        }
    }
}
