using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.DsmCc.Descriptors;
using skyscraper5.Skyscraper.IO;
using skyscraper5.Skyscraper.Plugins;

namespace skyscraper5.DsmCc.Message
{
    [SkyscraperPlugin]
    [DsmCcMessage(0x1002)]
    class DownloadInfoIndication : DsmCcMessage
    {
        public DownloadInfoIndication(byte[] buffer)
        {
            MemoryStream ms = new MemoryStream(buffer, false);

            DownloadId = ms.ReadUInt32BE();
            BlockSize = ms.ReadUInt16BE();
            WindowSize = ms.ReadUInt8();
            AckPeriod = ms.ReadUInt8();
            TcDownloadWindow = ms.ReadUInt32BE();
            TcDownloadScenario = ms.ReadUInt32BE();
            
            this.CompatibilityDescriptor = new CompatibilityDescriptor(ms);

            if (ms.GetAvailableBytes() < 2)
            {
                Valid = false;
                return;
            }

            ushort numberOfModules = ms.ReadUInt16BE();
            Modules = new Module[numberOfModules];
            for (int i = 0; i < numberOfModules; i++)
            {
                if (ms.GetAvailableBytes() < 8)
                {
                    Valid = false;
                    return;
                }

                Modules[i] = new Module();
                Modules[i].ID = ms.ReadUInt16BE();
                Modules[i].Size = ms.ReadUInt32BE();
                Modules[i].Version = ms.ReadUInt8();
                byte moduleInfoLength = ms.ReadUInt8();
                if (ms.GetAvailableBytes() < moduleInfoLength)
                {
                    Valid = false;
                    return;
                }

                Modules[i].ModuleInfo = ms.ReadBytes(moduleInfoLength);
            }

            if (ms.GetAvailableBytes() < 2)
            {
                Valid = false;
                return;
            }

            ushort privateDataLength = ms.ReadUInt16BE();
            if (privateDataLength < ms.GetAvailableBytes())
            {
                PrivateData = ms.ReadBytes(privateDataLength);
            }

            Valid = true;
        }
        
        public byte[] PrivateData { get; private set; }

        public Module[] Modules { get; private set; }

        public class Module
        {
            public ushort ID { get; internal set; }
            public uint Size { get; internal set; }
            public byte Version { get; internal set; }
            public byte[] ModuleInfo { get; internal set; }
        }

        public CompatibilityDescriptor CompatibilityDescriptor { get; private set; }

        public uint TcDownloadScenario { get; private set; }

        public uint TcDownloadWindow { get; private set; }

        public byte AckPeriod { get; private set; }

        public byte WindowSize { get; private set; }

        public ushort BlockSize { get; private set; }

        public uint DownloadId { get; private set; }
    }
}
