using JiShe.CollectBus.Common.Enums;
using JiShe.CollectBus.Common.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JiShe.CollectBus.Common.BuildSendDatas
{
    public static class Build188SendData
    {
        //起始字符
        private const string startStr = "68";

        //结束字符
        private const string endStr = "16";

        #region 188 下行命令

        /// <summary>
        /// 标准 188协议阀控
        /// </summary>
        /// <param name="waterMeterAddress"></param>
        /// <param name="mtype">表计类型</param>
        /// <returns></returns>
        public static List<string> BuildConfirm188WaterValve(string waterMeterAddress, bool state, string mtype = "10")
        {
            if (string.IsNullOrWhiteSpace(waterMeterAddress)) return null;

            var dataUnit = new List<string>() { "A0", "17", "00", state ? "55" : "99" };

            var dataList = Build188SendCommand(waterMeterAddress, "04", dataUnit);

            return dataList;
        }

        /// <summary>
        /// 构建188水表抄读下发数据单元
        /// </summary>
        /// <param name="waterMeterAddress"></param>
        /// <returns></returns>
        public static List<string> Build188WaterMeterReadingSendDataUnit(string waterMeterAddress)
        {

            var dataUnit = new List<string>() { "1F", "90", "00" };
            var dataList = Build188SendCommand(waterMeterAddress, "01", dataUnit);

            return dataList;
        }

        /// <summary>
        /// 构建188协议下发命令
        /// </summary>
        /// <param name="waterMeterAddress">水表地址</param>
        /// <param name="controlCode">控制码</param>
        /// <param name="dataUnit">数据域</param>
        /// <param name="meterType">表类型</param>
        /// <returns></returns>
        public static List<string> Build188SendCommand(string waterMeterAddress, string controlCode, List<string>? dataUnit = null, string meterType = "10")
        {
            //address.Substring(address.Length - 12, 12)
            var cmdStrList = new List<string>();
            cmdStrList.Add(startStr);
            cmdStrList.Add(meterType);

            waterMeterAddress = waterMeterAddress.PadLeft(14, '0');
            var addressList = waterMeterAddress.StringToPairs();
            addressList.Reverse();
            cmdStrList.AddRange(addressList);

            //控制码
            cmdStrList.Add(controlCode);

            var len = dataUnit != null ? dataUnit.Count.DecToHex().PadLeft(2, '0') : "00";
            cmdStrList.Add(len);
            if (dataUnit != null)
            {
                cmdStrList.AddRange(dataUnit);
            }

            var strSum = cmdStrList.Select(i => Convert.ToInt32(i, 16)).Sum().ToString("X");
            strSum = strSum.Substring(strSum.Length - 2);
            cmdStrList.Add(strSum);
            cmdStrList.Add(endStr);

            return cmdStrList;
        }

        /// <summary>
        /// 组装水表阀控
        /// </summary>
        /// <param name="waterMeterAddress">水表地址</param>
        /// <param name="password">The password.</param>
        /// <param name="protocol">The poprotocol.</param>
        /// <param name="state">if set to <c>true</c> [isopenvalve].</param>
        /// <returns></returns>
        public static List<string>? WaterMeterValveControl(string waterMeterAddress, string password, int protocol, bool state)
        {
            List<string>? turnData = null;
            if (protocol == 1)
                turnData = GetControlCode97(waterMeterAddress.Substring(waterMeterAddress.Length - 12, 12), password, state ? "3355" : "9966");//开阀/关阀
            else if (protocol == 30)
                turnData = GetControlCode07(waterMeterAddress.Substring(waterMeterAddress.Length - 12, 12), password, state ? "3355" : "9966");//开阀/关阀
            return turnData;
        }

        private static List<string> GetControlCode97(string waterMeterAddress, string password, string valueCode)
        {
            var dataList = new List<string>();
            var passwordList = password.StringToPairs();
            passwordList.Reverse();

            var valueCodeList = valueCode.StringToPairs();
            valueCodeList.Reverse();

            dataList.AddRange(valueCodeList);
            dataList.AddRange(passwordList);
            dataList.AddRange(valueCodeList);

            return GetCode(waterMeterAddress, "04", dataList);
        }

        private static List<string> GetControlCode07(string waterMeterAddress, string password, string valueCode)
        {
            var dataList = new List<string>();
            dataList.Add("02");

            var passwordList = password.StringToPairs();
            passwordList.Reverse();
            dataList.AddRange(passwordList);
            dataList.AddRange("01000000".StringToPairs());

            dataList.AddRange(valueCode.StringToPairs());

            dataList.Add("00");

            var time = DateTime.Now.AddDays(1).ToString("yyMMddHHmmss");
            var timeList = time.StringToPairs();
            timeList.Reverse();
            dataList.AddRange(timeList);

            return GetCode(waterMeterAddress, "1C", dataList);
        }

        public static List<string> GetCode(string waterMeterAddress, string controlCode, List<string> childDataList)
        {
            var dataList = new List<string> { startStr };

            waterMeterAddress = waterMeterAddress.PadLeft(12, '0');
            var addressList = waterMeterAddress.StringToPairs();
            addressList.Reverse();
            dataList.AddRange(addressList);

            dataList.Add(startStr);
            dataList.Add(controlCode);

            var num = childDataList.Count;
            dataList.Add(num.ToString("X2"));

            dataList.AddRange(childDataList.AddHex33());

            var cs = dataList.Select(it => Convert.ToInt32(it, 16)).Sum().ToString("X2");
            cs = cs.Substring(cs.Length - 2, 2);
            dataList.Add(cs);

            dataList.Add(endStr);

            return dataList;
        }


        public static object GetAnalyzeValue(this List<string> hexStringList, CommandChunkEnum188 chunk)
        {
            if (hexStringList.Count < 11)
            {
                return null;
            }

            switch (chunk)
            {
                case CommandChunkEnum188.A:
                    var aHexList = hexStringList[(int)CommandChunkEnum188.A].Take(7).ToList();
                    aHexList.Reverse();
                    return string.Join("", aHexList.Skip(1).Take(6).ToList());
                case CommandChunkEnum188.C:
                    var cHex = hexStringList[(int)CommandChunkEnum188.C];
                    return cHex;
                case CommandChunkEnum188.Data:
                    var lenIndex = (int)CommandChunkEnum188.L;
                    var len = hexStringList[lenIndex].HexToDec();

                    //验证长度 2=(帧校验和+结束字符）
                    if (hexStringList.Count - 2 != 11 + len)
                        return null;

                    var dataHexList = hexStringList.Skip(11).Take(len).ToList();
                    return dataHexList;
                default:
                    throw new ArgumentOutOfRangeException(nameof(chunk), chunk, null);
            }
        }

        //public double AnalyzeCurrentTotalRate(List<string> hexList)
        //{
        //    var str = string.Join("", hexList);
        //    var number = Convert.ToInt32(str) * 0.01;
        //    return number;
        //}

        #endregion
    }
}
