using EVESharp.Types.Collections;
using EVESharp.Types.Serialization;
using NUnit.Framework;

namespace EVESharp.Types.Unit.Marshaling;

public class ListMarshalingTests
{
    private static int    sListMarshaling_FirstValue  = 100;
    private static string sListMarshaling_SecondValue = "Hello World!";

    private static byte[] sListMarshaling_Empty = new byte[] {0x26};
    private static byte[] sListMarshaling_One = new byte[] {0x27, 0x06, 0x64};
    private static byte[] sListMarshaling_Two = new byte[] {0x15, 0x02, 0x06, 0x64, 0x13, 0x0C, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21};

    private static byte[] sListMarshaling_Big = new byte[]
    {
        0x15, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
    };
        
    [Test]
    public void ListMarshal_Empty()
    {
        PyList list = new PyList(0);

        byte[] output = Marshal.ToByteArray(list, false);
            
        Assert.AreEqual(sListMarshaling_Empty, output);
    }

    [Test]
    public void ListMarshal_One()
    {
        PyList list = new PyList(1) {[0] = sListMarshaling_FirstValue};

        byte[] output = Marshal.ToByteArray(list, false);

        Assert.AreEqual(sListMarshaling_One, output);
    }

    [Test]
    public void ListMarshal_Two()
    {
        PyList list = new PyList(2)
        {
            [0] = sListMarshaling_FirstValue,
            [1] = sListMarshaling_SecondValue
        };

        byte[] output = Marshal.ToByteArray(list, false);

        Assert.AreEqual(sListMarshaling_Two, output);
    }

    [Test]
    public void ListMarshal_Big()
    {
        PyList result = new PyList();
            
        for(int i = byte.MaxValue + 1; i > 0; i --)
            result.Add(null);

        byte[] output = Marshal.ToByteArray(result, false);

        Assert.AreEqual(sListMarshaling_Big, output);
    }

    [Test]
    public void ListUnmarshal_Empty()
    {
        PyDataType value = Unmarshal.ReadFromByteArray(sListMarshaling_Empty, false);
            
        Assert.IsInstanceOf<PyList>(value);

        PyList list = value as PyList;

        Assert.AreEqual(0, list.Count);
    }

    [Test]
    public void ListUnmarshal_One()
    {
        PyDataType value = Unmarshal.ReadFromByteArray(sListMarshaling_One, false);
            
        Assert.IsInstanceOf<PyList>(value);

        PyList list = value as PyList;

        Assert.AreEqual(1, list.Count);
        Assert.IsInstanceOf<PyInteger>(list[0]);
        Assert.AreEqual(sListMarshaling_FirstValue, (list[0] as PyInteger).Value);
    }

    [Test]
    public void ListUnmarshal_Two()
    {
        PyDataType value = Unmarshal.ReadFromByteArray(sListMarshaling_Two, false);
            
        Assert.IsInstanceOf<PyList>(value);

        PyList list = value as PyList;

        Assert.AreEqual(2, list.Count);
        Assert.IsInstanceOf<PyInteger>(list[0]);
        Assert.AreEqual(sListMarshaling_FirstValue, (list[0] as PyInteger).Value);
        Assert.IsInstanceOf<PyString>(list[1]);
        Assert.AreEqual(sListMarshaling_SecondValue, (list[1] as PyString).Value);
    }

    [Test]
    public void ListUnmarshal_Big()
    {
        PyDataType value = Unmarshal.ReadFromByteArray(sListMarshaling_Big, false);
            
        Assert.IsInstanceOf<PyList>(value);

        PyList list = value as PyList;
            
        Assert.AreEqual(256, list.Count);

        foreach (PyDataType entry in list)
            Assert.AreEqual(null, entry);
    }
}