using PkmnLib.Static.Libraries;

namespace PkmnLib.Dynamic.Libraries.DataLoaders;

/// <summary>
/// Loads type data from a CSV file.
/// </summary>
public static class TypeDataLoader
{
    private static readonly char[] CommonCsvDelimiters = ['|', ','];

    /// <summary>
    /// Loads the type library from a CSV file.
    /// </summary>
    public static TypeLibrary LoadTypeLibrary(Stream stream)
    {
        var library = new TypeLibrary();

        using var reader = new StreamReader(stream);
        var header = reader.ReadLine();
        if (header == null)
            throw new InvalidDataException("Type data is empty.");
        var delimiter = CommonCsvDelimiters.FirstOrDefault(header.Contains);
        if (delimiter == default)
            throw new InvalidDataException("No valid delimiter found in type data.");

        var types = header.Split(delimiter, StringSplitOptions.RemoveEmptyEntries)!;
        if (!types.Any())
            throw new InvalidDataException("No types found in type data.");

        foreach (var type in types.Skip(1))
            library.RegisterType(type);

        while (!reader.EndOfStream)
        {
            var line = reader.ReadLine();
            if (line == null)
                break;
            var values = line.Split(delimiter, StringSplitOptions.RemoveEmptyEntries)!;
            var type = values[0];
            if (!library.TryGetTypeIdentifier(type, out var typeId))
                throw new InvalidDataException($"Type {type} not found in type library.");
            for (var i = 1; i < values.Length; i++)
            {
                var effectiveness = float.Parse(values[i]);
                if (effectiveness < 0.0)
                {
                    throw new InvalidDataException(
                        $"Effectiveness for {type} against {types[i]} is invalid: {effectiveness}. Must be greater than or equal to 0.0.");
                }
                library.TryGetTypeIdentifier(types[i], out var defendingTypeId);
                library.SetEffectiveness(typeId, defendingTypeId, effectiveness);
            }
        }

        return library;
    }
}