using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Skyscraper;
using skyscraper5.Skyscraper.IO;

namespace skyscraper5.Dvb.SystemSoftwareUpdate
{
    class SystemSoftwareUpdateInfo : Validatable
    {
        public SystemSoftwareUpdateInfo(byte[] buffer)
        {
            if (buffer.Length == 0)
            {
                Valid = false;
                return;
            }
            MemoryStream ms = new MemoryStream(buffer, false);
            byte ouiDataLength = ms.ReadUInt8();
            if (ouiDataLength > ms.GetAvailableBytes())
            {
                Valid = false;
                return;
            }
            byte[] ouiBytes = ms.ReadBytes(ouiDataLength);
            DecodeOuis(ouiBytes);
            PrivateData = ms.ReadBytes(ms.GetAvailableBytes());
            this.Valid = true;
        }
        
        public byte[] PrivateData { get; private set; }

        private void DecodeOuis(byte[] buffer)
        {
            List<Oui> result = new List<Oui>();
            MemoryStream ms = new MemoryStream(buffer, false);
            while (ms.GetAvailableBytes() > 5)
            {
                Oui oui = new Oui();
                oui.OUI = BitConverter.ToString(ms.ReadBytes(3));
                byte readUInt8 = ms.ReadUInt8();
                oui.UpdateType = readUInt8 & 0x0f;
                readUInt8 = ms.ReadUInt8();
                oui.UpdateVersioningFlag = readUInt8 & 0x20;
                oui.UpdateVersion = readUInt8 & 0x1f;
                byte selectorLength = ms.ReadUInt8();
                if (ms.GetAvailableBytes() >= selectorLength)
                    oui.Selector = ms.ReadBytes(selectorLength);
                result.Add(oui);
            }

            Ouis = result.AsReadOnly();
        }

        public ReadOnlyCollection<Oui> Ouis { get; private set; }

        public class Oui
        {
            public string OUI { get; set; }
            public int UpdateType { get; set; }
            public int UpdateVersioningFlag { get; set; }
            public int UpdateVersion { get; set; }
            public byte[] Selector { get; set; }
        }

    }
}
