using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FLY.Modbus
{

    /// <summary>
    /// property 与 PLC寄存器 更新操作
    /// </summary>
    public class RegisterData : AreaManager
    {

        /// <summary>
        /// 
        /// </summary>
        public RegisterData(PLCAddressArea area, int maxOfOneRead) : base(area, maxOfOneRead)
        {

        }

        /// <summary>
        /// 根据当前regs的配置指定读寄存器的计划
        /// </summary>
        public override void MakePlan()
        {

            if (regs == null)
            {
                throw new Exception("还没有执行 BuildArray()");
            }
            lock (plan_buffer)
            {
                plan_buffer.Clear();

                int addr = -1;
                int num = 0;
                for (int i = 0; i < regs.Count(); i++)
                {
                    if (!regs[i].isNeedUpdate)
                        continue;

                    if (addr == -1)//上次的计划已经结束，重新来
                    {
                        addr = regs[i].addr;
                        UInt16[] plc_value = (UInt16[])regs[i].plcValue;
                        num = plc_value.Count();
                        if (num > maxOfOneRead)
                        {
                            //一片区域已经大于 最大读取寄存器数，分拆
                            while (num > maxOfOneRead)
                            {
                                plan.Add(new Plan(area, addr, maxOfOneRead));
                                addr += maxOfOneRead;
                                num -= maxOfOneRead;
                            }
                            if (num > 0)//最后一些
                                plan.Add(new Plan(area, addr, num));
                            addr = -1;
                        }
                    }
                    else
                    {
                        UInt16[] plc_value = (UInt16[])regs[i].plcValue;
                        //新的 最后一个寄存器地址
                        int addr_end = regs[i].addr + plc_value.Count() - 1;
                        //总数量
                        int n = addr_end - addr + 1;

                        if (n <= maxOfOneRead)
                        {
                            //还没长于单次最大数量，累计进去
                            num = n;
                        }
                        else
                        {
                            //不行，太长，之前的截断，添加到 计划
                            plan_buffer.Add(new Plan(area, addr, num));
                            addr = -1;
                            //reg[i] 退回，下次再运算
                            i--;
                        }
                    }

                }

                if (addr != -1)//上次还 添加到计划中
                {
                    plan_buffer.Add(new Plan(area, addr, num));
                    addr = -1;
                }
                isPlanChanged = true;
            }
        }
    }
}
