using RioJoy.Core.Overlay;
using SkiaSharp;

namespace RioJoy.Overlay;

/// <summary>
/// Generates a profile's cockpit wallpaper: renders a label set onto the overlay
/// template's base image and writes a PNG. Resolves the template's
/// <see cref="OverlayTemplate.BaseImagePath"/> relative to the template file's
/// directory (so a <c>regions.json</c> + sibling <c>riojoy.png</c> work as a unit).
/// The runtime calls this on profile activation; an editor can call it for preview.
/// </summary>
public sealed class ProfileWallpaperGenerator
{
    private readonly SkiaOverlayRenderer _renderer;

    public ProfileWallpaperGenerator(SkiaOverlayRenderer? renderer = null) =>
        _renderer = renderer ?? new SkiaOverlayRenderer();

    /// <summary>
    /// Render <paramref name="labels"/> onto the template's base image and write a
    /// PNG to <paramref name="outputPath"/>; returns the output path.
    /// </summary>
    /// <param name="templateDirectory">
    /// Directory the template's relative <see cref="OverlayTemplate.BaseImagePath"/>
    /// is resolved against (normally the folder holding the regions.json).
    /// </param>
    public string Generate(
        OverlayTemplate template,
        string templateDirectory,
        IDictionary<string, string> labels,
        string outputPath,
        OverlayLayoutOptions? options = null)
    {
        if (template is null) throw new ArgumentNullException(nameof(template));
        if (labels is null) throw new ArgumentNullException(nameof(labels));
        if (string.IsNullOrWhiteSpace(outputPath)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(outputPath));
        if (string.IsNullOrWhiteSpace(template.BaseImagePath))
            throw new InvalidOperationException("OverlayTemplate.BaseImagePath is not set.");

        string basePath = Path.IsPathRooted(template.BaseImagePath)
            ? template.BaseImagePath
            : Path.Combine(templateDirectory, template.BaseImagePath);

        using SKBitmap baseImage = SKBitmap.Decode(basePath)
            ?? throw new InvalidOperationException($"Could not decode base image: {basePath}");

        byte[] png = _renderer.RenderToPng(template, labels, baseImage, options);

        string? dir = Path.GetDirectoryName(Path.GetFullPath(outputPath));
        if (!string.IsNullOrEmpty(dir))
            Directory.CreateDirectory(dir);
        File.WriteAllBytes(outputPath, png);
        return outputPath;
    }
}
