using System;
using System.Collections.Generic;
using System.Text;

using System;
using OpenCvSharp;
namespace OpenCVStudio_v0
{
    public sealed class GammaCorrectionExecutor : IImageBlockExecutor
    {
        public string BlockType => "GammaCorrection";
        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));
            double gamma = projectManager.GetBlockParameter(block.Id, "Gamma", 1.0);
            ValidateGamma(gamma);
            if (input.Depth() != MatType.CV_8U) throw new NotSupportedException($"Гамма-коррекция через LUT поддерживает только 8-битные изображения. Текущий тип: {input.Type()}");
            using Mat lookupTable = CreateLookupTable(gamma);
            Mat output = new Mat();
            try
            {
                Cv2.LUT(input, lookupTable, output);
                if (output.Empty()) throw new InvalidOperationException("Гамма-коррекция вернула пустое изображение.");
                return output;
            }
            catch { output.Dispose(); throw; }
        }
        private static Mat CreateLookupTable(double gamma)
        {
            Mat lookupTable = new Mat(1, 256, MatType.CV_8UC1);
            double inverseGamma = 1.0 / gamma;
            for (int i = 0; i < 256; i++)
            {
                double normalized = i / 255.0;
                double corrected = Math.Pow(normalized, inverseGamma);
                int value = (int)Math.Round(corrected * 255.0);
                value = Math.Clamp(value, 0, 255);
                lookupTable.Set(0, i, (byte)value);
            }
            return lookupTable;
        }
        private static void ValidateGamma(double gamma)
        {
            if (double.IsNaN(gamma) || double.IsInfinity(gamma) || gamma < 0.01 || gamma > 10.0)
                throw new ArgumentException("Гамма должна находиться в диапазоне от 0,01 до 10,0.");
        }
    }
}