using Microsoft.VisualBasic.CompilerServices;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
// Nicht gemergte Änderung aus Projekt "Pilz.UI (net8.0-windows)" 
// Vor:
// Imports System.Windows.Forms
// Imports System.Drawing
// Nach:
// Imports System.Drawing
// Imports System.Windows.Forms
using System.Windows.Forms;

namespace Pilz.UI;


public class Highlighter : Component
{

    private Dictionary<Control, eHighlightColor> _Highlights = new Dictionary<Control, eHighlightColor>();
    private Dictionary<Control, bool> _HighlightOnFocus = new Dictionary<Control, bool>();

    protected override void Dispose(bool disposing)
    {
        if (_ContainerControl is not null)
        {
            _ContainerControl.SizeChanged -= ContainerControlSizeChanged;
            _ContainerControl.HandleCreated -= ContainerControlHandleCreated;
        }

        if (_HighlightPanel is not null && _HighlightPanel.Parent is null && !_HighlightPanel.IsDisposed)
        {
            _HighlightPanel.Dispose();
            _HighlightPanel = null;
        }
        else
        {
            _HighlightPanel = null;
        }

        base.Dispose(disposing);
    }

    [DefaultValue(false)]
    [Localizable(true)]
    [Description("Indicates whether control is highlighted when it receives input focus.")]
    public bool GetHighlightOnFocus(Control c)
    {
        if (_HighlightOnFocus.ContainsKey(c))
            return _HighlightOnFocus[c];

        return false;
    }

    public void SetHighlightOnFocus(Control c, bool highlight)
    {
        if (c is null)
            throw new NullReferenceException();

        if (_HighlightOnFocus.ContainsKey(c))
        {

            if (!highlight)
                RemoveHighlightOnFocus(_HighlightOnFocus, c);

            return;
        }

        if (highlight)
            AddHighlightOnFocus(_HighlightOnFocus, c);
    }

    private void AddHighlightOnFocus(Dictionary<Control, bool> highlightOnFocus, Control c)
    {
        c.Enter += ControlHighlightEnter;
        c.Leave += ControlHighlightLeave;
        c.VisibleChanged += ControlHighlightVisibleChanged;
        highlightOnFocus.Add(c, true);
    }

    private void ControlHighlightVisibleChanged(object sender, EventArgs e)
    {
        if (_HighlightPanel is not null && Conversions.ToBoolean(Operators.ConditionalCompareObjectEqual(_HighlightPanel.FocusHighlightControl, sender, false)))
            UpdateHighlighterRegion();
    }

    private void ControlHighlightLeave(object sender, EventArgs e)
    {
        if (_HighlightPanel is not null)
            _HighlightPanel.FocusHighlightControl = null;
        UpdateHighlighterRegion();
    }

    private void ControlHighlightEnter(object sender, EventArgs e)
    {
        if (_HighlightPanel is not null)
        {
            if (!_HighlightPanel.Visible)
                _HighlightPanel.Visible = true;
            _HighlightPanel.BringToFront();
            _HighlightPanel.FocusHighlightControl = (Control)sender;
        }

        UpdateHighlighterRegion();
    }

    private void RemoveHighlightOnFocus(Dictionary<Control, bool> highlightOnFocus, Control c)
    {
        c.Enter -= ControlHighlightEnter;
        c.Leave -= ControlHighlightLeave;
        c.VisibleChanged -= ControlHighlightVisibleChanged;
        highlightOnFocus.Remove(c);
    }

    [DefaultValue(eHighlightColor.None)]
    [Localizable(true)]
    [Description("Indicates the highlight color that is applied to the control.")]
    public eHighlightColor GetHighlightColor(Control c)
    {
        if (_Highlights.ContainsKey(c))
            return _Highlights[c];

        return eHighlightColor.None;
    }

    public void SetHighlightColor(Control c, eHighlightColor highlightColor)
    {
        if (_Highlights.ContainsKey(c))
        {

            if (highlightColor == eHighlightColor.None)
                RemoveHighlight(_Highlights, c);
            else
            {
                var color = _Highlights[c];
                RemoveHighlight(_Highlights, c);
                AddHighlight(_Highlights, c, highlightColor);
            }
        }
        else if (highlightColor != eHighlightColor.None)
        {
            AddHighlight(_Highlights, c, highlightColor);
        }
    }

    private Dictionary<TabControl, int> _TabControl2 = new Dictionary<TabControl, int>();
    private Dictionary<Panel, int> _ParentPanel = new Dictionary<Panel, int>();

    private void AddHighlight(Dictionary<Control, eHighlightColor> highlights, Control c, eHighlightColor highlightColor)
    {
        highlights.Add(c, highlightColor);
        c.LocationChanged += new EventHandler(ControlLocationChanged);
        c.SizeChanged += new EventHandler(ControlSizeChanged);
        c.VisibleChanged += new EventHandler(ControlVisibleChanged);

        if (_HighlightPanel is not null)
        {
            if (!_HighlightPanel.Visible)
                _HighlightPanel.Visible = true;
            _HighlightPanel.BringToFront();
        }

        if (c.Parent is null)
            c.ParentChanged += ControlParentChanged;
        else
        {
            AddTabControlHandlers(c);
        }

        UpdateHighlighterRegion();
    }

    private void ControlParentChanged(object sender, EventArgs e)
    {
        Control c = (Control)sender;
        c.ParentChanged -= ControlParentChanged;
        AddTabControlHandlers(c);
    }

    private void AddTabControlHandlers(Control c)
    {
        TabControl tab2 = GetParentControl(c, typeof(TabControl)) as TabControl;

        if (tab2 is not null)
        {

            if (_TabControl2.ContainsKey(tab2))
                _TabControl2[tab2] = _TabControl2[tab2] + 1;
            else
            {
                _TabControl2.Add(tab2, 1);
                tab2.SelectedIndexChanged += WinFormsTabSelectedIndexChanged;
            }
        }
        else
        {
            Panel parentPanel = GetParentControl(c, typeof(Panel)) as Panel;

            if (parentPanel is not null)
            {

                if (_ParentPanel.ContainsKey(parentPanel))
                    _ParentPanel[parentPanel] = _ParentPanel[parentPanel] + 1;
                else
                {
                    _ParentPanel.Add(parentPanel, 1);
                    parentPanel.Resize += ParentPanelResized;
                    parentPanel.LocationChanged += ParentPanelLocationChanged;
                }
            }
        }
    }

    private void ParentPanelLocationChanged(object sender, EventArgs e)
    {
        UpdateHighlights();
    }

    private void ParentPanelResized(object sender, EventArgs e)
    {
        UpdateHighlights();
    }

    private void WinFormsTabSelectedIndexChanged(object sender, EventArgs e)
    {
        UpdateHighlighterRegion();
    }

    private Control GetParentControl(Control c, Type parentType)
    {
        var parent = c.Parent;

        while (parent is not null)
        {
            if (parentType.IsAssignableFrom(parent.GetType()))
                return parent;
            parent = parent.Parent;
        }

        return null;
    }

    private void ControlVisibleChanged(object sender, EventArgs e)
    {
        UpdateHighlighterRegion();
    }

    private void ControlSizeChanged(object sender, EventArgs e)
    {
        UpdateHighlighterRegion();
    }

    private void ControlLocationChanged(object sender, EventArgs e)
    {
        UpdateHighlighterRegion();
    }

    private void UpdateHighlighterRegion()
    {
        if (_HighlightPanel is not null)
            _HighlightPanel.UpdateRegion();
    }

    public void UpdateHighlights()
    {
        UpdateHighlighterRegion();
    }

    private void RemoveHighlight(Dictionary<Control, eHighlightColor> highlights, Control c)
    {
        highlights.Remove(c);
        c.LocationChanged -= new EventHandler(ControlLocationChanged);
        c.SizeChanged -= new EventHandler(ControlSizeChanged);
        c.VisibleChanged -= new EventHandler(ControlVisibleChanged);
        TabControl tab2 = GetParentControl(c, typeof(TabControl)) as TabControl;

        if (tab2 is not null)
        {

            if (_TabControl2.ContainsKey(tab2))
            {

                if (_TabControl2[tab2] == 1)
                {
                    _TabControl2.Remove(tab2);
                    tab2.SelectedIndexChanged -= WinFormsTabSelectedIndexChanged;
                }
                else
                {
                    _TabControl2[tab2] = _TabControl2[tab2] - 1;
                }
            }
        }
        else
        {
            Panel parentPanel = GetParentControl(c, typeof(Panel)) as Panel;

            if (parentPanel is not null)
            {

                if (_ParentPanel.ContainsKey(parentPanel))
                {

                    if (_ParentPanel[parentPanel] == 1)
                    {
                        _ParentPanel.Remove(parentPanel);
                        parentPanel.LocationChanged -= ParentPanelLocationChanged;
                        parentPanel.SizeChanged -= ParentPanelResized;
                    }
                    else
                    {
                        _ParentPanel[parentPanel] = _ParentPanel[parentPanel] - 1;
                    }
                }
            }
        }

        UpdateHighlighterRegion();
    }

    internal Dictionary<Control, eHighlightColor> Highlights
    {
        get
        {
            return _Highlights;
        }
    }

    private eHighlightColor _FocusHighlightColor = eHighlightColor.Blue;

    [DefaultValue(eHighlightColor.Blue)]
    [Category("Appearance")]
    [Description("Indicates the highlight focus color.")]
    [Localizable(true)]
    public eHighlightColor FocusHighlightColor
    {
        get
        {
            return _FocusHighlightColor;
        }
        set
        {
            _FocusHighlightColor = value;

            if (_HighlightPanel is not null)
            {
                _HighlightPanel.FocusHighlightColor = value;
                UpdateHighlighterRegion();
            }
        }
    }

    private HighlightPanel _HighlightPanel = null;
    private Control _ContainerControl = null;

    [Description("Indicates container control highlighter is bound to. Should be set to parent form.")]
    [Category("Behavior")]
    public Control ContainerControl
    {
        get
        {
            return _ContainerControl;
        }
        set
        {

            if (DesignMode)
            {
                _ContainerControl = value;
                return;
            }

            if (!ReferenceEquals(_ContainerControl, value))
            {

                if (_ContainerControl is not null)
                {
                    _ContainerControl.SizeChanged -= ContainerControlSizeChanged;
                    _ContainerControl.HandleCreated -= ContainerControlHandleCreated;
                    if (_HighlightPanel is not null && ReferenceEquals(_HighlightPanel.Parent, _ContainerControl))
                        _ContainerControl.Controls.Remove(_HighlightPanel);
                }

                _ContainerControl = value;

                if (_ContainerControl is not null)
                {

                    if (_HighlightPanel is null)
                    {
                        _HighlightPanel = new HighlightPanel(_Highlights);
                        _HighlightPanel.FocusHighlightColor = _FocusHighlightColor;
                        _HighlightPanel.Margin = new Padding(0);
                        _HighlightPanel.Padding = new Padding(0);
                        _HighlightPanel.CustomHighlightColors = _CustomHighlightColors;
                        _HighlightPanel.Visible = false;
                    }

                    _ContainerControl.SizeChanged += ContainerControlSizeChanged;
                    _ContainerControl.HandleCreated += ContainerControlHandleCreated;
                    _ContainerControl.Controls.Add(_HighlightPanel);
                    UpdateHighlightPanelBounds();
                }
            }
        }
    }

    private void ContainerControlHandleCreated(object sender, EventArgs e)
    {
        if (_Highlights.Count > 0 && _HighlightPanel is not null && !_HighlightPanel.Visible)
            _HighlightPanel.Visible = true;
    }

    private void UpdateHighlightPanelBounds()
    {
        var bounds = new Rectangle(0, 0, _ContainerControl.ClientRectangle.Width, _ContainerControl.ClientRectangle.Height);

        if (_HighlightPanel is not null)
        {
            if (_HighlightPanel.Parent is Form)
            {
                Form form = _HighlightPanel.Parent as Form;

                if (form.AutoSize)
                {
                    bounds.X += form.Padding.Left;
                    bounds.Y += form.Padding.Top;
                    bounds.Width -= form.Padding.Horizontal;
                    bounds.Height -= form.Padding.Vertical;
                }
            }

            if (_HighlightPanel.Bounds.Equals(bounds))
                _HighlightPanel.UpdateRegion();
            else
            {
                _HighlightPanel.Bounds = bounds;
            }

            _HighlightPanel.BringToFront();
        }
    }

    private System.Windows.Forms.Timer _DelayTimer = null;

    private void ContainerControlSizeChanged(object sender, EventArgs e)
    {
        Form form = sender as Form;

        if (form is not null)
        {

            if (_DelayTimer is null)
            {
                _DelayTimer = new();
                _DelayTimer.Interval = 100;
                _DelayTimer.Tick += new EventHandler(DelayTimerTick);
                _DelayTimer.Start();
            }

            return;
        }

        UpdateHighlightPanelBounds();
    }

    private void DelayTimerTick(object sender, EventArgs e)
    {
        var timer = _DelayTimer;
        _DelayTimer = null;
        timer.Tick -= new EventHandler(DelayTimerTick);
        timer.Stop();
        timer.Dispose();
        UpdateHighlightPanelBounds();
    }

    private Color[] _CustomHighlightColors = null;

    [Category("Appearance")]
    [Description("Array of colors used to render custom highlight color. Control expects 3 colors in array to be specified which define the highlight border.")]
    public Color[] CustomHighlightColors
    {
        get
        {
            return _CustomHighlightColors;
        }
        set
        {
            _CustomHighlightColors = value;

            if (_HighlightPanel is not null)
            {
                _HighlightPanel.CustomHighlightColors = _CustomHighlightColors;
                _HighlightPanel.Invalidate();
            }
        }
    }

}

public enum eHighlightColor
{
    None,
    Red,
    Blue,
    Green,
    Orange,
    Custom
}