using System;
using Minint.Core.Models;

namespace Minint.Core.Services.Impl;

public sealed class FragmentService : IFragmentService
{
    public void CopyFragment(
        MinintDocument srcDoc, int srcLayerIndex,
        int srcX, int srcY, int regionWidth, int regionHeight,
        MinintDocument dstDoc, int dstLayerIndex,
        int dstX, int dstY,
        int containerWidth, int containerHeight)
    {
        ArgumentOutOfRangeException.ThrowIfNegative(srcLayerIndex);
        ArgumentOutOfRangeException.ThrowIfNegative(dstLayerIndex);
        if (srcLayerIndex >= srcDoc.Layers.Count)
            throw new ArgumentOutOfRangeException(nameof(srcLayerIndex));
        if (dstLayerIndex >= dstDoc.Layers.Count)
            throw new ArgumentOutOfRangeException(nameof(dstLayerIndex));

        var srcLayer = srcDoc.Layers[srcLayerIndex];
        var dstLayer = dstDoc.Layers[dstLayerIndex];

        int clippedSrcX = Math.Max(srcX, 0);
        int clippedSrcY = Math.Max(srcY, 0);
        int clippedEndX = Math.Min(srcX + regionWidth, containerWidth);
        int clippedEndY = Math.Min(srcY + regionHeight, containerHeight);

        for (int sy = clippedSrcY; sy < clippedEndY; sy++)
        {
            int dy = dstY + (sy - srcY);
            if (dy < 0 || dy >= containerHeight) continue;

            for (int sx = clippedSrcX; sx < clippedEndX; sx++)
            {
                int dx = dstX + (sx - srcX);
                if (dx < 0 || dx >= containerWidth) continue;

                int srcIdx = srcLayer.Pixels[sy * containerWidth + sx];
                if (srcIdx == 0) continue; // skip transparent

                RgbaColor color = srcDoc.Palette[srcIdx];
                int dstIdx = dstDoc.EnsureColorCached(color);
                dstLayer.Pixels[dy * containerWidth + dx] = dstIdx;
            }
        }
    }
}
