using System;
using OpenCvSharp;
namespace OpenCVStudio_v0
{
    public sealed class MedianBlurExecutor : IImageBlockExecutor
    {
        private const int MinimumKernelSize = 3; private const int MaximumKernelSize = 99;
        public string BlockType => "MedianBlur";
        public Mat Execute(Mat input, ProjectBlock block, ProjectManager projectManager)
        {
            ArgumentNullException.ThrowIfNull(input);
            ArgumentNullException.ThrowIfNull(block);
            ArgumentNullException.ThrowIfNull(projectManager);
            if (input.Empty()) throw new ArgumentException("В блок медианного фильтра передано пустое изображение.", nameof(input));
            int kernelSize = projectManager.GetBlockParameter(block.Id, "KernelSize", 5);
            ValidateKernelSize(kernelSize);
            ValidateImageSize(input, kernelSize);
            Mat output = new Mat();
            try
            {
                Cv2.MedianBlur(input, output, kernelSize);
                if (output.Empty()) throw new InvalidOperationException("Медианный фильтр вернул пустое изображение.");
                return output;
            }
            catch { output.Dispose(); throw; }
        }
        private static void ValidateKernelSize(int kernelSize)
        {
            if (kernelSize < MinimumKernelSize || kernelSize > MaximumKernelSize)
                throw new ArgumentOutOfRangeException(nameof(kernelSize), kernelSize, $"Размер ядра должен быть от {MinimumKernelSize} до {MaximumKernelSize}.");
            if (kernelSize % 2 == 0) throw new ArgumentException("Размер ядра медианного фильтра должен быть нечётным.", nameof(kernelSize));
        }
        private static void ValidateImageSize(Mat input, int kernelSize)
        {
            if (input.Width < kernelSize || input.Height < kernelSize)
                throw new ArgumentException($"Размер ядра {kernelSize} × {kernelSize} превышает размер изображения {input.Width} × {input.Height}.");
        }
    }
}