using System;
using OpenCvSharp;

namespace OpenCVStudio_v0
{
    public sealed class Filter2DExecutor : IImageBlockExecutor
    {
        public string BlockType => "Filter2D";

        public Mat Execute(Mat input, ProjectBlock block, ProjectManager projectManager)
        {
            if (input == null)
                throw new ArgumentNullException(nameof(input));
            if (input.Empty())
                throw new InvalidOperationException("Filter2D: изображение пустое.");
            Filter2DKernel kernelType = projectManager.GetBlockParameter(block.Id, "Kernel", Filter2DKernel.Identity);
            using Mat kernel = CreateKernel(kernelType);
            Mat result = new Mat();
            Cv2.Filter2D(input, result, -1, kernel);
            return result;
        }

        private static Mat CreateKernel(Filter2DKernel type)
        {
            Mat kernel = new Mat(3, 3, MatType.CV_32FC1);
            float[] data = type switch
            {
                Filter2DKernel.Blur3x3 => new float[] { 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9, 1f / 9 },
                Filter2DKernel.Sharpen => new float[] { 0, -1, 0, -1, 5, -1, 0, -1, 0 },
                Filter2DKernel.Edge => new float[] { -1, -1, -1, -1, 8, -1, -1, -1, -1 },
                Filter2DKernel.Emboss => new float[] { -2, -1, 0, -1, 1, 1, 0, 1, 2 },
                _ => new float[] { 0, 0, 0, 0, 1, 0, 0, 0, 0 }
            };
            for (int y = 0; y < 3; y++)
            {
                for (int x = 0; x < 3; x++)
                {
                    kernel.Set(y, x, data[y * 3 + x]);
                }
            }
            return kernel;
        }
    }
}