using System.IO;
using System.Net.NetworkInformation;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.Plugins;
using skyscraper5.Skyscraper.Scraper;

namespace skyscraper5.Docsis.MacManagement
{
	[SkyscraperPlugin]
	[MacManagementMessageType(1,3)]
    internal class UpstreamBandwidthAllocation : MacManagementMessage
    {
        public UpstreamBandwidthAllocation(PhysicalAddress source, PhysicalAddress destination, byte[] buffer) : base(source, destination, buffer)
        {
            MemoryStream ms = new MemoryStream(buffer, false);
            
            UpstreamChannelId = ms.ReadUInt8();
            UcdCount = ms.ReadUInt8();
            NumberOfElements = ms.ReadUInt8();
            byte reserved = ms.ReadUInt8();

            AllocStartTime = ms.ReadUInt32BE();

            AckTime = ms.ReadUInt32BE();

            RangingBackoffStart = ms.ReadUInt8();
            RangingBackoffEnd = ms.ReadUInt8();
            DataBackoffStart = ms.ReadUInt8();
            DataBackoffEnd = ms.ReadUInt8();

            long mapEntries = ms.GetAvailableBytes() / 4;
            Map = new Triplet<uint, uint, uint>[mapEntries];

            for (long i = 0; i < mapEntries; i++)
            {
                uint mapEntry = ms.ReadUInt32BE();
                uint sid = (mapEntry & 0xfffc0000) >> 18;
                uint iuc = (mapEntry & 0x0003c000) >> 14;
                uint off = (mapEntry & 0x00003fff);
                Map[i] = new Triplet<uint, uint, uint>(sid, iuc, off);
            }
            Valid = true;
        }

        public Triplet<uint,uint,uint>[] Map { get; private set; }

        public byte DataBackoffEnd { get; private set; }

        public byte DataBackoffStart { get; private set; }

        public byte RangingBackoffEnd { get; private set; }

        public byte RangingBackoffStart { get; private set; }

        public uint AckTime { get; private set; }

        public uint AllocStartTime { get; private set; }

        public byte NumberOfElements { get; private set; }

        public byte UcdCount { get; private set; }

        public byte UpstreamChannelId { get; private set; }
    }
}
