using System.Security.Cryptography;

namespace Harmonia.Core.Imaging;

public class SongPictureInfo
{
    public required byte[] Data { get; init; }
    public string? ImageHash { get; private set; }
    public required string ImageName { get; init; }
    public long Size => Data.Length;

    private SongPictureInfo()
    {

    }

    public static async Task<SongPictureInfo> FromStreamAsync(Stream stream, CancellationToken cancellationToken)
    {
        string imageHash = ComputeImageHash(stream);

        return await GetSongPictureInfoAsync(stream, "Embedded", imageHash, cancellationToken);
    }

    private static string ComputeImageHash(Stream stream)
    {
        using var md5 = MD5.Create();
        byte[] hash = md5.ComputeHash(stream);

        return Convert.ToHexStringLower(hash);
    }

    public static async Task<SongPictureInfo> FromFileAsync(string fileName, CancellationToken cancellationToken)
    {
        using FileStream fileStream = File.OpenRead(fileName);

        return await GetSongPictureInfoAsync(fileStream, fileName, cancellationToken: cancellationToken);
    }

    private static async Task<SongPictureInfo> GetSongPictureInfoAsync(Stream stream, string imageName, string? imageHash = null, CancellationToken cancellationToken = default)
    {
        return new()
        {
            Data = await GetImageDataAsync(stream, cancellationToken),
            ImageHash = imageHash,
            ImageName = imageName
        };
    }

    public static async Task<byte[]> GetImageDataAsync(Stream stream, CancellationToken cancellationToken)
    {
        stream.Seek(0, SeekOrigin.Begin);

        using MemoryStream memoryStream = new();
        await stream.CopyToAsync(memoryStream, cancellationToken);

        return memoryStream.ToArray();
    }
}