using RRQMCore.ByteManager;
using RRQMSocket;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProjectManagementSystem.Device.CasunBox
{
    public class BoxDataHandlingAdapter : DataHandlingAdapter
    {
        /// <summary>
        /// 获取已设置的数据包的长度
        /// </summary>
        public int FixedSize { get; private set; } = 14;

        /// <summary>
        /// 临时包
        /// </summary>
        private ByteBlock tempByteBlock;

        /// <summary>
        /// 包剩余长度
        /// </summary>
        private int surPlusLength = 0;

        public BytePool BytePoolEx { get; set; } = new BytePool();

        /// <summary>
        /// 预处理
        /// </summary>
        /// <param name="byteBlock"></param>
        protected override void PreviewReceived(ByteBlock byteBlock)
        {
            bool lightProtocol = byteBlock.Buffer[0] == 0x20 && byteBlock.Length % 16 == 0;
            bool callProtocol = byteBlock.Buffer[0] == 0x10 && byteBlock.Length % 14 == 0 && byteBlock.Buffer[byteBlock.Length - 1] == 0x03;

            //报警灯协议长度16
            if (lightProtocol)
            {
                FixedSize = 16;
                if (this.tempByteBlock != null)
                {
                    this.tempByteBlock.Dispose();
                    this.tempByteBlock = null;
                }
            }
            else if(callProtocol)
            {
                FixedSize = 14;
                if (this.tempByteBlock != null)
                {
                    this.tempByteBlock.Dispose();
                    this.tempByteBlock = null;
                }
            }

            byte[] buffer = byteBlock.Buffer;
            int r = (int)byteBlock.Length;
            if (this.tempByteBlock == null)
            {
                SplitPackage(buffer, 0, r);
            }
            else
            {
                if (surPlusLength == r)
                {
                    this.tempByteBlock.Write(buffer, 0, surPlusLength);
                    PreviewHandle(this.tempByteBlock);
                    this.tempByteBlock.Dispose();
                    this.tempByteBlock = null;
                    surPlusLength = 0;
                }
                else if (surPlusLength < r)
                {
                    this.tempByteBlock.Write(buffer, 0, surPlusLength);
                    PreviewHandle(this.tempByteBlock);
                    this.tempByteBlock.Dispose();
                    this.tempByteBlock = null;
                    SplitPackage(buffer, surPlusLength, r);
                }
                else
                {
                    this.tempByteBlock.Write(buffer, 0, r);
                    surPlusLength -= r;
                }
            }
        }

        private void SplitPackage(byte[] dataBuffer, int index, int r)
        {
            while (index < r)
            {
                if (r - index >= this.FixedSize)
                {
                    ByteBlock byteBlock = this.BytePoolEx.GetByteBlock(this.FixedSize);
                    byteBlock.Write(dataBuffer, index, this.FixedSize);
                    PreviewHandle(byteBlock);
                    surPlusLength = 0;
                }
                else//半包
                {
                    this.tempByteBlock = this.BytePoolEx.GetByteBlock(this.FixedSize);
                    surPlusLength = this.FixedSize - (r - index);
                    this.tempByteBlock.Write(dataBuffer, index, r - index);
                }
                index += this.FixedSize;
            }
        }

        protected virtual void PreviewHandle(ByteBlock byteBlock)
        {
            try
            {
                if ((byteBlock.Buffer[0] == 0x10 && byteBlock.Length == 14 && byteBlock.Buffer[byteBlock.Length - 1] == 0x03)
                    || (byteBlock.Buffer[0] == 0x20 && byteBlock.Length == 16))
                {
                    this.GoReceived(byteBlock, null);
                }
            }
            finally
            {
                byteBlock.Dispose();
            }
        }

        protected override void PreviewSend(byte[] buffer, int offset, int length, bool isAsync)
        {
            this.GoSend(buffer, offset, length, isAsync);
        }
    }
}
