using System.Reflection;

namespace Wonderking.Game;

public abstract class DataReader<T>
{
    protected DataReader(string path)
    {
        Path = path;
        _xorKey = GetXorKey();
        SizeOfEntry = GetSizeOfEntry();
        _datFileName = GetDatFileName();
        DatFileContent = GetDatFileContent(path).ToArray();
    }

    private protected string Path { get; init; }

    public abstract uint GetAmountOfEntries();
    public abstract T GetEntry(uint entryId);

    private static ushort GetSizeOfEntry()
    {
        return typeof(T).GetCustomAttribute<GameDataMetadataAttribute>()?.DataEntrySize ??
               throw new NotSupportedException("DataEntrySize is null");
    }

    private static string GetDatFileName()
    {
        return typeof(T).GetCustomAttribute<GameDataMetadataAttribute>()?.DatFileName ??
               throw new NotSupportedException("DatFileName is null");
    }

    private static byte GetXorKey()
    {
        return typeof(T).GetCustomAttribute<GameDataMetadataAttribute>()?.XorKey ??
               throw new NotSupportedException("XorKey is null");
    }

    private readonly byte _xorKey;
    protected readonly ushort SizeOfEntry;
    private readonly string _datFileName;

    protected byte[] DatFileContent { get; }

    private Span<byte> GetDatFileContent(string path)
    {
        var fileData = File.ReadAllBytes(path + this._datFileName);
        var data = new byte[fileData.Length];

        for (var i = 0; i < fileData.Length; i++)
        {
            data[i] = (byte)(fileData[i] ^ this._xorKey);
        }

        return data;
    }
}