using System;
using System.ComponentModel;
namespace OpenCVStudio_v0
{
    public sealed class AddBorderBlockProperties
    {
        private readonly ProjectManager projectManager; private readonly ProjectBlock projectBlock;
        private int top; private int bottom; private int left; private int right;
        private RotateBorderMode borderMode; private double borderValue;
        public AddBorderBlockProperties(ProjectManager projectManager, ProjectBlock projectBlock)
        {
            this.projectManager = projectManager ?? throw new ArgumentNullException(nameof(projectManager));
            this.projectBlock = projectBlock ?? throw new ArgumentNullException(nameof(projectBlock));
            top = projectManager.GetBlockParameter(projectBlock.Id, "Top", 50);
            bottom = projectManager.GetBlockParameter(projectBlock.Id, "Bottom", 50);
            left = projectManager.GetBlockParameter(projectBlock.Id, "Left", 50);
            right = projectManager.GetBlockParameter(projectBlock.Id, "Right", 50);
            borderMode = projectManager.GetBlockParameter(projectBlock.Id, "BorderMode", RotateBorderMode.Constant);
            borderValue = projectManager.GetBlockParameter(projectBlock.Id, "BorderValue", 0.0);
        }
        [Category("Размер полей")]
        [DisplayName("Сверху")]
        [Description("Количество добавляемых пикселей сверху.")]
        public int Top
        {
            get => top;
            set
            {
                ValidateBorderSize(value, "Верхнее поле");
                if (top == value) return;
                top = value;
                projectManager.SetBlockParameter(projectBlock.Id, "Top", value);
            }
        }
        [Category("Размер полей")]
        [DisplayName("Снизу")]
        [Description("Количество добавляемых пикселей снизу.")]
        public int Bottom
        {
            get => bottom;
            set
            {
                ValidateBorderSize(value, "Нижнее поле");
                if (bottom == value) return;
                bottom = value;
                projectManager.SetBlockParameter(projectBlock.Id, "Bottom", value);
            }
        }
        [Category("Размер полей")]
        [DisplayName("Слева")]
        [Description("Количество добавляемых пикселей слева.")]
        public int Left
        {
            get => left;
            set
            {
                ValidateBorderSize(value, "Левое поле");
                if (left == value) return;
                left = value;
                projectManager.SetBlockParameter(projectBlock.Id, "Left", value);
            }
        }
        [Category("Размер полей")]
        [DisplayName("Справа")]
        [Description("Количество добавляемых пикселей справа.")]
        public int Right
        {
            get => right;
            set
            {
                ValidateBorderSize(value, "Правое поле");
                if (right == value) return;
                right = value;
                projectManager.SetBlockParameter(projectBlock.Id, "Right", value);
            }
        }
        [Category("Заполнение")]
        [DisplayName("Режим")]
        [Description("Constant — постоянное значение. Replicate — повтор крайнего пикселя. Reflect — зеркальное отражение. Reflect101 — отражение без повторения крайнего пикселя.")]
        public RotateBorderMode BorderMode
        {
            get => borderMode;
            set
            {
                if (!Enum.IsDefined(value)) throw new ArgumentOutOfRangeException(nameof(value), value, "Неизвестный режим заполнения полей.");
                if (borderMode == value) return;
                borderMode = value;
                projectManager.SetBlockParameter(projectBlock.Id, "BorderMode", value);
            }
        }
        [Category("Заполнение")]
        [DisplayName("Значение фона")]
        [Description("Значение заполнения в режиме Constant. 0 — чёрный, 255 — белый.")]
        public double BorderValue
        {
            get => borderValue;
            set
            {
                if (double.IsNaN(value) || double.IsInfinity(value) || value < 0.0 || value > 255.0)
                    throw new ArgumentOutOfRangeException(nameof(value), value, "Значение фона должно быть от 0 до 255.");
                if (Math.Abs(borderValue - value) < double.Epsilon) return;
                borderValue = value;
                projectManager.SetBlockParameter(projectBlock.Id, "BorderValue", 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 ValidateBorderSize(int value, string parameterName)
        {
            if (value < 0 || value > 100000)
                throw new ArgumentOutOfRangeException(nameof(value), value, $"{parameterName} должно быть от 0 до 100000 пикселей.");
        }
    }
}