using System;
using System.Collections.Generic;
using System.Linq;
using SkiaSharp;
using StabilityMatrix.Core.Extensions;

namespace StabilityMatrix.Avalonia.Helpers;

public static class ImageProcessor
{
    /// <summary>
    /// Get the dimensions of a grid that can hold the given amount of images.
    /// </summary>
    public static (int rows, int columns) GetGridDimensionsFromImageCount(int count)
    {
        if (count <= 1)
            return (1, 1);
        if (count == 2)
            return (1, 2);

        // Prefer one extra row over one extra column,
        // the row count will be the floor of the square root
        // and the column count will be floor of count / rows
        var rows = (int)Math.Floor(Math.Sqrt(count));
        var columns = (int)Math.Floor((double)count / rows);
        return (rows, columns);
    }

    public static SKImage CreateImageGrid(IReadOnlyList<SKImage> images, int spacing = 0)
    {
        if (images.Count == 0)
            throw new ArgumentException("Must have at least one image");

        var (rows, columns) = GetGridDimensionsFromImageCount(images.Count);

        var singleWidth = images[0].Width;
        var singleHeight = images[0].Height;

        // Make output image
        using var output = new SKBitmap(
            singleWidth * columns + spacing * (columns - 1),
            singleHeight * rows + spacing * (rows - 1)
        );

        // Draw images
        using var canvas = new SKCanvas(output);

        foreach (
            var (row, column) in Enumerable.Range(0, rows).Product(Enumerable.Range(0, columns))
        )
        {
            // Stop if we have drawn all images
            var index = row * columns + column;
            if (index >= images.Count)
                break;

            // Get image
            var image = images[index];

            // Draw image
            var destination = new SKRect(
                singleWidth * column + spacing * column,
                singleHeight * row + spacing * row,
                singleWidth * column + spacing * column + image.Width,
                singleHeight * row + spacing * row + image.Height
            );
            canvas.DrawImage(image, destination);
        }

        return SKImage.FromBitmap(output);
    }
}
