using PLC.Siemens.Protocol.ReadData;
using PlcSiemens.O;
using PlcSiemens.Protocol.Common;
using PlcSiemens.Protocol.ReadData;

namespace PlcSiemens.ProtocolHandle
{
    /// <summary>
    ///
    /// </summary>
    public class ReadHandle : IPacketHandle
    {
        public ushort PduLength { get; set; }
        public DataItem DataItem { get; set; }
        public ResultCode ResultCode { get; private set; }

        public void Handle(IIsoSender sender)
        {
            if (DataItem.Db > 65535 || DataItem.Length < 1)
                throw new ArgumentException("参数异常");
            if (DataItem.DataType == DataType.Bit && DataItem.Length > 1)
                throw new ArgumentException("Bit只能读取一位");

            var sizeByte = DataItem.SizeByte;
            var maxCount = (ushort)((PduLength - 0x0A - 6 - 2) / sizeByte);
            var totalCount = DataItem.Length;
            var offset = DataItem.Start;
            var curCopyPos = 0;
            DataItem.Data = new byte[sizeByte * totalCount];

            DataItem currentItem = new DataItem()
            {
                AreaType = DataItem.AreaType,
                DataType = DataItem.DataType,
                Db = DataItem.Db,
                Start = DataItem.Start,
                Length = 0
            };

            ResultCode = ResultCode.OKFF;
            while (totalCount > 0 && ResultCode == ResultCode.OKFF)
            {
                var curCount = totalCount;
                if (curCount > maxCount)
                    curCount = maxCount;

                currentItem.Length = curCount;
                currentItem.Start = offset;

                ReadRequest read = new ReadRequest();
                read.ListItems = new List<DataItem> { currentItem };

                ReadResponse res = sender.IsoSend<ReadRequest, ReadResponse>(read);
                if (res == null)
                    throw new Exception("plc连接异常");
                ResultCode = res.Header.Error;
                if (ResultCode != ResultCode.OK)
                {
                    break;
                }

                ResultCode = ResultCode.OKFF;
                foreach (var b in res.DataItems)
                {
                    DataItem.Err = (ResultCode)b.ReturnCode;
                    if (DataItem.Err == ResultCode.OKFF)
                    {
                        Array.Copy(b.Data, 0, DataItem.Data, curCopyPos, currentItem.SizeByte * curCount);
                    }
                    else
                    {
                        ResultCode = (ResultCode)b.ReturnCode;
                        break;
                    }
                }

                curCopyPos += (ushort)(currentItem.SizeByte * curCount);
                offset += (ushort)(currentItem.SizeByte * curCount);//res.DataItems[0].DataLength;
                totalCount -= curCount;
            }
            if (ResultCode == ResultCode.OKFF) ResultCode = ResultCode.OK;
        }
    }
}
