using System;
using OpenCvSharp;

namespace OpenCVStudio_v0
{
    public sealed class DemosaicingExecutor : IImageBlockExecutor
    {
        public string BlockType => "Demosaicing";

        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));
            if (input.Channels() != 1)
            {
                throw new InvalidOperationException("Demosaicing требует одноканальное Bayer изображение.");
            }
            DemosaicingPattern pattern = projectManager.GetBlockParameter(block.Id, "Pattern", DemosaicingPattern.RGGB);
            DemosaicingAlgorithm algorithm = projectManager.GetBlockParameter(block.Id, "Algorithm", DemosaicingAlgorithm.EdgeAware);
            ColorConversionCodes code = GetConversionCode(pattern, algorithm);
            Mat output = new Mat();
            try
            {
                Cv2.Demosaicing(input, output, code);
                return output;
            }
            catch
            {
                output.Dispose();
                throw;
            }
        }

        private static ColorConversionCodes GetConversionCode(DemosaicingPattern pattern, DemosaicingAlgorithm algorithm)
        {
            return (pattern, algorithm) switch
            {
                (DemosaicingPattern.RGGB, DemosaicingAlgorithm.Bilinear) => ColorConversionCodes.BayerBG2BGR,
                (DemosaicingPattern.BGGR, DemosaicingAlgorithm.Bilinear) => ColorConversionCodes.BayerRG2BGR,
                (DemosaicingPattern.GRBG, DemosaicingAlgorithm.Bilinear) => ColorConversionCodes.BayerGB2BGR,
                (DemosaicingPattern.GBRG, DemosaicingAlgorithm.Bilinear) => ColorConversionCodes.BayerGR2BGR,
                (DemosaicingPattern.RGGB, DemosaicingAlgorithm.VNG) => ColorConversionCodes.BayerBG2BGR_VNG,
                (DemosaicingPattern.BGGR, DemosaicingAlgorithm.VNG) => ColorConversionCodes.BayerRG2BGR_VNG,
                (DemosaicingPattern.GRBG, DemosaicingAlgorithm.VNG) => ColorConversionCodes.BayerGB2BGR_VNG,
                (DemosaicingPattern.GBRG, DemosaicingAlgorithm.VNG) => ColorConversionCodes.BayerGR2BGR_VNG,
                (DemosaicingPattern.RGGB, DemosaicingAlgorithm.EdgeAware) => ColorConversionCodes.BayerBG2BGR_EA,
                (DemosaicingPattern.BGGR, DemosaicingAlgorithm.EdgeAware) => ColorConversionCodes.BayerRG2BGR_EA,
                (DemosaicingPattern.GRBG, DemosaicingAlgorithm.EdgeAware) => ColorConversionCodes.BayerGB2BGR_EA,
                (DemosaicingPattern.GBRG, DemosaicingAlgorithm.EdgeAware) => ColorConversionCodes.BayerGR2BGR_EA,
                (DemosaicingPattern.RGGB, DemosaicingAlgorithm.Gray) => ColorConversionCodes.BayerBG2GRAY,
                (DemosaicingPattern.BGGR, DemosaicingAlgorithm.Gray) => ColorConversionCodes.BayerRG2GRAY,
                (DemosaicingPattern.GRBG, DemosaicingAlgorithm.Gray) => ColorConversionCodes.BayerGB2GRAY,
                (DemosaicingPattern.GBRG, DemosaicingAlgorithm.Gray) => ColorConversionCodes.BayerGR2GRAY,
                _ => ColorConversionCodes.BayerBG2BGR
            };
        }
    }
}