using System;
using OpenCvSharp;
namespace OpenCVStudio_v0
{
    public sealed class NormalizeExecutor : IImageBlockExecutor
    {
        public string BlockType => "Normalize";
        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));
            NormalizeMode mode = projectManager.GetBlockParameter(block.Id, "Mode", NormalizeMode.MinMax);
            double alpha = projectManager.GetBlockParameter(block.Id, "Alpha", 0.0);
            double beta = projectManager.GetBlockParameter(block.Id, "Beta", 255.0);
            ValidateParameters(mode, alpha, beta);
            NormTypes normType = ConvertNormalizeMode(mode);
            Mat output = new Mat();
            try
            {
                Cv2.Normalize(input, output, alpha, beta, normType, dtype: -1);
                if (output.Empty()) throw new InvalidOperationException("Normalize вернул пустое изображение.");
                return output;
            }
            catch { output.Dispose(); throw; }
        }
        private static NormTypes ConvertNormalizeMode(NormalizeMode mode)
        {
            return mode switch
            {
                NormalizeMode.MinMax => NormTypes.MinMax,
                NormalizeMode.L1 => NormTypes.L1,
                NormalizeMode.L2 => NormTypes.L2,
                _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, "Неизвестный режим нормализации.")
            };
        }
        private static void ValidateParameters(NormalizeMode mode, double alpha, double beta)
        {
            if (double.IsNaN(alpha) || double.IsInfinity(alpha)) throw new ArgumentException("Alpha содержит недопустимое значение.");
            if (double.IsNaN(beta) || double.IsInfinity(beta)) throw new ArgumentException("Beta содержит недопустимое значение.");
            if (mode == NormalizeMode.MinMax && beta <= alpha) throw new ArgumentException("При режиме MinMax значение Beta должно быть больше Alpha.");
            if (mode != NormalizeMode.MinMax && alpha < 0) throw new ArgumentException("Для режимов L1 и L2 значение Alpha не должно быть отрицательным.");
        }
    }
}