using System;
using System.Drawing;
using System.Windows.Forms;

namespace OpenCVStudio_v0
{
    public sealed class PipelineBlockControl : UserControl
    {
        private readonly Label labelOrder;
        private readonly Label labelName;
        private readonly Label labelType;
        private readonly FlowLayoutPanel panelButtons;
        private readonly Button buttonSelectFile;
        private readonly Button buttonPreview;
        private readonly Button buttonMoveUp;
        private readonly Button buttonMoveDown;
        private readonly Button buttonDelete;
        private bool isSelected;

        public ProjectBlock ProjectBlock { get; }

        public event EventHandler? BlockSelected;
        public event EventHandler? FileSelectionRequested;
        public event EventHandler? PreviewRequested;
        public event EventHandler? MoveUpRequested;
        public event EventHandler? MoveDownRequested;
        public event EventHandler? DeleteRequested;

        public PipelineBlockControl(ProjectBlock projectBlock)
        {
            ProjectBlock = projectBlock ?? throw new ArgumentNullException(nameof(projectBlock));
            Height = 72;
            Width = 360;
            Margin = new Padding(8);
            Padding = new Padding(6);
            BackColor = Color.White;
            BorderStyle = BorderStyle.FixedSingle;
            Cursor = Cursors.Hand;
            labelOrder = new Label { AutoSize = false, Width = 42, Dock = DockStyle.Left, TextAlign = ContentAlignment.MiddleCenter, Font = new Font(Font, FontStyle.Bold) };
            /*
             * Теперь кнопок пять:
             *
             * 📁 👁 ▲ ▼ ✕
             *
             * Поэтому ширину панели увеличиваем
             * со 144 до 180 пикселей.
             */
            panelButtons = new FlowLayoutPanel { AutoSize = false, Width = 180, Dock = DockStyle.Right, FlowDirection = FlowDirection.LeftToRight, WrapContents = false, Padding = new Padding(0), Margin = new Padding(0) };
            buttonSelectFile = CreateCommandButton(text: "📁", toolTipText: "Выбрать файл изображения");
            buttonPreview = CreateCommandButton(text: "👁", toolTipText: "Показать предпросмотр через Cv2.ImShow");
            buttonMoveUp = CreateCommandButton(text: "▲", toolTipText: "Переместить блок вверх");
            buttonMoveDown = CreateCommandButton(text: "▼", toolTipText: "Переместить блок вниз");
            buttonDelete = CreateCommandButton(text: "✕", toolTipText: "Удалить блок");
            /*
             * По умолчанию кнопка выбора файла скрыта.
             * BlockLibraryController покажет её только
             * для ImageSource и SecondImageSource.
             */
            buttonSelectFile.Visible = false;
            panelButtons.Controls.Add(buttonSelectFile);
            panelButtons.Controls.Add(buttonPreview);
            panelButtons.Controls.Add(buttonMoveUp);
            panelButtons.Controls.Add(buttonMoveDown);
            panelButtons.Controls.Add(buttonDelete);
            labelType = new Label { AutoSize = false, Dock = DockStyle.Bottom, Height = 22, TextAlign = ContentAlignment.MiddleLeft, ForeColor = Color.DimGray, Padding = new Padding(4, 0, 0, 0) };
            labelName = new Label { AutoSize = false, Dock = DockStyle.Fill, TextAlign = ContentAlignment.MiddleLeft, Font = new Font(Font.FontFamily, 10, FontStyle.Bold), Padding = new Padding(4, 0, 0, 0) };
            Controls.Add(labelName);
            Controls.Add(labelType);
            Controls.Add(panelButtons);
            Controls.Add(labelOrder);
            Click += Control_Click;
            labelOrder.Click += Control_Click;
            labelName.Click += Control_Click;
            labelType.Click += Control_Click;
            buttonSelectFile.Click += ButtonSelectFile_Click;
            buttonPreview.Click += ButtonPreview_Click;
            buttonMoveUp.Click += ButtonMoveUp_Click;
            buttonMoveDown.Click += ButtonMoveDown_Click;
            buttonDelete.Click += ButtonDelete_Click;
            UpdateView();
        }

        public void UpdateView()
        {
            labelOrder.Text = (ProjectBlock.Order + 1).ToString();
            labelName.Text = ProjectBlock.Name;
            labelType.Text = ProjectBlock.BlockType;
            UpdateBackgroundColor();
        }

        public void SetSelected(bool selected)
        {
            isSelected = selected;
            UpdateBackgroundColor();
        }

        public void SetMoveButtonsEnabled(bool canMoveUp, bool canMoveDown)
        {
            buttonMoveUp.Enabled = canMoveUp;
            buttonMoveDown.Enabled = canMoveDown;
        }

        /// <summary>
        /// Показывает или скрывает кнопку
        /// выбора файла изображения.
        /// </summary>
        public void SetFileSelectionVisible(bool visible)
        {
            buttonSelectFile.Visible = visible;
        }

        private Button CreateCommandButton(string text, string toolTipText)
        {
            Button button = new Button { Width = 32, Height = 32, Text = text, Margin = new Padding(2, 12, 2, 0), Padding = new Padding(0), FlatStyle = FlatStyle.Flat, TabStop = false, Cursor = Cursors.Hand };
            button.FlatAppearance.BorderSize = 1;
            ToolTip toolTip = new ToolTip();
            toolTip.SetToolTip(button, toolTipText);
            return button;
        }

        private void UpdateBackgroundColor()
        {
            if (isSelected)
            {
                BackColor = Color.LightSteelBlue;
                return;
            }
            BackColor = ProjectBlock.IsEnabled ? Color.White : Color.Gainsboro;
        }

        private void SelectThisBlock()
        {
            BlockSelected?.Invoke(this, EventArgs.Empty);
        }

        private void Control_Click(object? sender, EventArgs e)
        {
            SelectThisBlock();
        }

        private void ButtonSelectFile_Click(object? sender, EventArgs e)
        {
            FileSelectionRequested?.Invoke(this, EventArgs.Empty);
        }

        private void ButtonPreview_Click(object? sender, EventArgs e)
        {
            SelectThisBlock();
            PreviewRequested?.Invoke(this, EventArgs.Empty);
        }

        private void ButtonMoveUp_Click(object? sender, EventArgs e)
        {
            SelectThisBlock();
            MoveUpRequested?.Invoke(this, EventArgs.Empty);
        }

        private void ButtonMoveDown_Click(object? sender, EventArgs e)
        {
            SelectThisBlock();
            MoveDownRequested?.Invoke(this, EventArgs.Empty);
        }

        private void ButtonDelete_Click(object? sender, EventArgs e)
        {
            SelectThisBlock();
            DeleteRequested?.Invoke(this, EventArgs.Empty);
        }
    }
}