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

using System;
using System.ComponentModel;
namespace OpenCVStudio_v0
{
    public sealed class NormalizeBlockProperties
    {
        private readonly ProjectManager projectManager; private readonly ProjectBlock projectBlock;
        private NormalizeMode mode; private double alpha; private double beta;
        public NormalizeBlockProperties(ProjectManager projectManager, ProjectBlock projectBlock)
        {
            this.projectManager = projectManager ?? throw new ArgumentNullException(nameof(projectManager));
            this.projectBlock = projectBlock ?? throw new ArgumentNullException(nameof(projectBlock));
            mode = projectManager.GetBlockParameter(projectBlock.Id, "Mode", NormalizeMode.MinMax);
            alpha = projectManager.GetBlockParameter(projectBlock.Id, "Alpha", 0.0);
            beta = projectManager.GetBlockParameter(projectBlock.Id, "Beta", 255.0);
        }
        [Category("Нормализация")]
        [DisplayName("Режим")]
        [Description("Способ нормализации значений изображения. Для обычной обработки изображения рекомендуется MinMax.")]
        public NormalizeMode Mode
        {
            get => mode;
            set
            {
                if (mode == value) return;
                mode = value;
                projectManager.SetBlockParameter(projectBlock.Id, "Mode", value);
            }
        }
        [Category("Диапазон")]
        [DisplayName("Минимум / Alpha")]
        [Description("Для MinMax задаёт минимальное значение результата. Для L1, L2 и Inf задаёт норму.")]
        public double Alpha
        {
            get => alpha;
            set
            {
                ValidateNumber(value, "Alpha");
                if (Math.Abs(alpha - value) < double.Epsilon) return;
                alpha = value;
                projectManager.SetBlockParameter(projectBlock.Id, "Alpha", value);
                if (mode == NormalizeMode.MinMax && beta <= alpha)
                {
                    beta = alpha + 1.0;
                    projectManager.SetBlockParameter(projectBlock.Id, "Beta", beta);
                }
            }
        }
        [Category("Диапазон")]
        [DisplayName("Максимум / Beta")]
        [Description("Для MinMax задаёт максимальное значение результата. В остальных режимах обычно не используется.")]
        public double Beta
        {
            get => beta;
            set
            {
                ValidateNumber(value, "Beta");
                if (mode == NormalizeMode.MinMax && value <= alpha) value = alpha + 1.0;
                if (Math.Abs(beta - value) < double.Epsilon) return;
                beta = value;
                projectManager.SetBlockParameter(projectBlock.Id, "Beta", value);
            }
        }
        [Category("Блок")]
        [DisplayName("Название")]
        [ReadOnly(true)]
        public string BlockName => projectBlock.Name;
        [Category("Блок")]
        [DisplayName("Тип")]
        [ReadOnly(true)]
        public string BlockType => projectBlock.BlockType;
        [Category("Блок")]
        [DisplayName("Позиция")]
        [ReadOnly(true)]
        public int Position => projectBlock.Order + 1;
        private static void ValidateNumber(double value, string parameterName)
        {
            if (double.IsNaN(value) || double.IsInfinity(value) || value < -1000000 || value > 1000000)
                throw new ArgumentOutOfRangeException(nameof(value), value, $"{parameterName} содержит недопустимое значение.");
        }
    }
}