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

using System.ComponentModel;
namespace OpenCVStudio_v0
{
    public sealed class MorphologyBlockProperties
    {
        private readonly ProjectManager projectManager; private readonly ProjectBlock projectBlock;
        private MorphologyOperationMode operation; private MorphologyKernelShape kernelShape; private int kernelWidth; private int kernelHeight; private int iterations;
        public MorphologyBlockProperties(ProjectManager projectManager, ProjectBlock projectBlock)
        {
            this.projectManager = projectManager ?? throw new ArgumentNullException(nameof(projectManager));
            this.projectBlock = projectBlock ?? throw new ArgumentNullException(nameof(projectBlock));
            operation = projectManager.GetBlockParameter(projectBlock.Id, "Operation", MorphologyOperationMode.Open);
            kernelShape = projectManager.GetBlockParameter(projectBlock.Id, "KernelShape", MorphologyKernelShape.Rectangle);
            kernelWidth = projectManager.GetBlockParameter(projectBlock.Id, "KernelWidth", 3);
            kernelHeight = projectManager.GetBlockParameter(projectBlock.Id, "KernelHeight", 3);
            iterations = projectManager.GetBlockParameter(projectBlock.Id, "Iterations", 1);
        }
        [Category("Операция")]
        [DisplayName("Операция")]
        [Description("Тип морфологической обработки.")]
        public MorphologyOperationMode Operation
        {
            get => operation;
            set
            {
                if (operation == value) return;
                operation = value;
                projectManager.SetBlockParameter(projectBlock.Id, "Operation", value);
            }
        }
        [Category("Ядро")]
        [DisplayName("Форма ядра")]
        [Description("Rectangle, Ellipse или Cross.")]
        public MorphologyKernelShape KernelShape
        {
            get => kernelShape;
            set
            {
                if (kernelShape == value) return;
                kernelShape = value;
                projectManager.SetBlockParameter(projectBlock.Id, "KernelShape", value);
            }
        }
        [Category("Ядро")]
        [DisplayName("Ширина")]
        [Description("Ширина структурного элемента.")]
        public int KernelWidth
        {
            get => kernelWidth;
            set
            {
                ValidateKernelSize(value, "Ширина ядра");
                if (kernelWidth == value) return;
                kernelWidth = value;
                projectManager.SetBlockParameter(projectBlock.Id, "KernelWidth", value);
            }
        }
        [Category("Ядро")]
        [DisplayName("Высота")]
        [Description("Высота структурного элемента.")]
        public int KernelHeight
        {
            get => kernelHeight;
            set
            {
                ValidateKernelSize(value, "Высота ядра");
                if (kernelHeight == value) return;
                kernelHeight = value;
                projectManager.SetBlockParameter(projectBlock.Id, "KernelHeight", value);
            }
        }
        [Category("Выполнение")]
        [DisplayName("Количество повторов")]
        [Description("Сколько раз будет выполнена операция.")]
        public int Iterations
        {
            get => iterations;
            set
            {
                if (value < 1 || value > 100) throw new ArgumentOutOfRangeException(nameof(value), value, "Количество повторов должно быть от 1 до 100.");
                if (iterations == value) return;
                iterations = value;
                projectManager.SetBlockParameter(projectBlock.Id, "Iterations", 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 ValidateKernelSize(int value, string parameterName)
        {
            if (value < 1 || value > 255) throw new ArgumentOutOfRangeException(nameof(value), value, $"{parameterName} должна быть от 1 до 255.");
            if (value % 2 == 0) throw new ArgumentException($"{parameterName} должна быть нечётной.");
        }
    }
}