namespace OF_DL.Widevine;

internal class PsshBox
{
    private static readonly byte[] s_psshHeader = [0x70, 0x73, 0x73, 0x68];

    private PsshBox(List<byte[]> kids, byte[] data)
    {
        KIDs = kids;
        Data = data;
    }

    public List<byte[]> KIDs { get; set; }
    public byte[] Data { get; set; }

    public static PsshBox FromByteArray(byte[] psshbox)
    {
        using MemoryStream stream = new(psshbox);

        stream.Seek(4, SeekOrigin.Current);
        byte[] header = new byte[4];
        stream.ReadExactly(header, 0, 4);

        if (!header.SequenceEqual(s_psshHeader))
        {
            throw new Exception("Not a pssh box");
        }

        stream.Seek(20, SeekOrigin.Current);
        byte[] kidCountBytes = new byte[4];
        stream.ReadExactly(kidCountBytes, 0, 4);

        if (BitConverter.IsLittleEndian)
        {
            Array.Reverse(kidCountBytes);
        }

        uint kidCount = BitConverter.ToUInt32(kidCountBytes);

        List<byte[]> kids = new();
        for (int i = 0; i < kidCount; i++)
        {
            byte[] kid = new byte[16];
            stream.ReadExactly(kid);
            kids.Add(kid);
        }

        byte[] dataLengthBytes = new byte[4];
        stream.ReadExactly(dataLengthBytes);

        if (BitConverter.IsLittleEndian)
        {
            Array.Reverse(dataLengthBytes);
        }

        uint dataLength = BitConverter.ToUInt32(dataLengthBytes);

        if (dataLength == 0)
        {
            return new PsshBox(kids, []);
        }

        byte[] data = new byte[dataLength];
        stream.ReadExactly(data);

        return new PsshBox(kids, data);
    }
}
