using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GeneralGommunication
{
    public interface IDev7E : INotifyPropertyChanged
    {
        /// <summary>
        /// 通讯速度测量模块
        /// </summary>
        CommSpeedMeasuring Csm { get; }

        /// <summary>
        /// 包出错次数
        /// </summary>
        int ErrCnt { get; }

        /// <summary>
        /// 连接成功；
        /// 当命令多次发送失败，IsConnected = false
        /// </summary>
        bool IsConnected { get; }

        /// <summary>
        /// 有数据需要发送
        /// </summary>
        event SendDataEventHandler SendMsgEvent;

        #region 模块运行接口

        /// <summary>
        /// 在接收事件中调用；
        /// 全部接收事件 及 超时事件也是在这里触发
        /// </summary>
        /// <param name="recBuf"></param>
        void RecMsg(byte[] recBuf);

        /// <summary>
        /// 复位全部状态，通常由于通讯模块检测到连接断开导致的
        /// </summary>
        void ResetMsg();
        #endregion
    }

    /// <summary>
    /// 有数据需要发送
    /// </summary>
    /// <param name="sender"></param>
    public delegate void SendMsgEventHander(object sender);

    /// <summary>
    /// 异常不回复
    /// </summary>
    /// <param name="asyncContext"></param>
    /// <param name="retData"></param>
    public delegate void CallBackHandler(object asyncContext, object retData);

    public class CallBackHandlerContext
    {
        public CallBackHandler asyncDelegate;
        public object asyncContext;
    }

    public class CallBackAttribute : Attribute
    {
        public Type RetType;
        public CallBackAttribute(Type type)
        {
            RetType = type;
        }
    }



    /// <summary>
    /// 通知指令
    /// </summary>
    public class COMMREQ
    {
        private byte[] prefix;
        /// <summary>
        /// 指令 前缀
        /// </summary>
        public byte[] Prefix 
        {
            get { return prefix; }
            set {
                prefix = value;
                updatePrefixString();
            }
        }
        public string PrefixString { get; private set; }
        void updatePrefixString() 
        {
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < Prefix.Count(); i++)
            {
                if (Prefix[i] >= 33 && Prefix[i] <= 126)
                    stringBuilder.Append((char)Prefix[i]);
                else
                    stringBuilder.Append($" 0x{Prefix[i]:X2} ");
            }
            PrefixString =  stringBuilder.ToString();
        }
        /// <summary>
        /// 回复数据 长度, 不含前序
        /// </summary>
        public int ResponseLen;

        /// <summary>
        /// 回复数据 总长度, 含前序
        /// </summary>
        public int ResponseTotalLen => Prefix.Length + ResponseLen;

        public delegate object ParseFuncPackHandler(byte[] pack, int dataIdx);

        public ParseFuncPackHandler ParseFuncPack;
        public delegate bool IsMatchHandler(COMMREQ commReq, byte[] pack, int dataIdx, object context, ref object retData);
        public IsMatchHandler IsMatch;
        public object IsMatchContext;
        public static byte[] ToPrefix(params object[] commands)
        {
            List<byte> bytes = new List<byte>();
            foreach (var command in commands)
            {
                if (command is string)
                {
                    var c = (string)command;
                    foreach (var _c in c)
                    {
                        bytes.Add((byte)_c);
                    }
                }
                else if (command is char)
                {
                    var c = (char)command;
                    bytes.Add((byte)c);
                }
                else if (command is byte)
                {
                    var c = (byte)command;
                    bytes.Add(c);
                }
                else if (command is UInt16)
                {
                    var c = (UInt16)command;
                    var bs = BitConverter.GetBytes(c);
                    bytes.AddRange(bs);
                }
                else if (command is UInt32)
                {
                    var c = (UInt32)command;
                    var bs = BitConverter.GetBytes(c);
                    bytes.AddRange(bs);
                }
                else if (command is int)
                {
                    var c = (int)command;
                    var bs = BitConverter.GetBytes(c);
                    bytes.AddRange(bs);
                }
                else if (command is byte[])
                {
                    var c = (byte[])command;
                    bytes.AddRange(c);
                }
                else
                {
                    throw new Exception("不支持该类型");
                }
            }
            if (bytes.Count < 2)
                throw new Exception("指令少于 2bytes");
            return bytes.ToArray();
        }


    }

    public abstract class COMMREQ_TransactionBase 
    {
        /// <summary>
        /// 回复 callback
        /// </summary>
        public CallBackHandler asyncDelegate;

        /// <summary>
        /// 上下文
        /// </summary>
        public object asyncContext;
    }
    /// <summary>
    /// 交易集合包
    /// </summary>
    public class COMMREQ_TransactionMulti : COMMREQ_TransactionBase
    {
        /// <summary>
        /// 交易集合
        /// </summary>
        public List<COMMREQ_Transaction> transactions = new List<COMMREQ_Transaction>();
    }
    
    
    public class COMMREQ_Transaction: COMMREQ_TransactionBase
    {
        /// <summary>
        /// 请求
        /// </summary>
        public COMMREQ commReq;

        /// <summary>
        /// 数据
        /// </summary>
        public byte[] datas;

        /// <summary>
        /// 数据的object 表达，只用于调试而已
        /// </summary>
        public object datasObj;

        /// <summary>
        /// 数据已经回复
        /// </summary>
        public bool hasRet;

        /// <summary>
        /// 回复的数据，只用于调试而已
        /// </summary>
        public object retData;
    }
}
