using System;
using OpenCvSharp;

namespace OpenCVStudio_v0
{
    /// <summary>
    /// Извлекает один канал
    /// из текущего изображения.
    /// </summary>
    public sealed class ExtractChannelExecutor : IImageBlockExecutor
    {
        public string BlockType => "ExtractChannel";

        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 channelIndex = projectManager.GetBlockParameter(block.Id, "ChannelIndex", 0);
            ValidateChannelIndex(input, channelIndex, block);
            Mat output = new Mat();
            try
            {
                Cv2.ExtractChannel(input, output, channelIndex);
                if (output.Empty())
                {
                    throw new InvalidOperationException($"Блок «{block.Name}» вернул пустое изображение.");
                }
                return output;
            }
            catch
            {
                output.Dispose();
                throw;
            }
        }

        private static void ValidateChannelIndex(Mat input, int channelIndex, ProjectBlock block)
        {
            int channelCount = input.Channels();
            if (channelCount <= 0)
            {
                throw new InvalidOperationException($"Блок «{block.Name}» получил изображение без каналов.");
            }
            if (channelIndex < 0 || channelIndex >= channelCount)
            {
                throw new InvalidOperationException($"Блок «{block.Name}» не может извлечь выбранный канал.\n\nВыбран канал: {channelIndex}\nКоличество каналов изображения: {channelCount}\n\nДопустимый диапазон: 0–{channelCount - 1}");
            }
        }
    }
}