namespace RyzStudio.Windows.Forms
{
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing;
    using System.Windows.Forms;

    [ToolboxItem(true)]
    public class PanelBook : Panel
    {
        public class PanelCollection : CollectionBase
        {
            protected PanelBook panelBook = null;

            public PanelCollection(PanelBook parentPanelBook) : base()
            {
                panelBook = parentPanelBook;
            }

            public PanelBook Parent => panelBook;

            public Panel this[int index] { get => (Panel)List[index]; set => List[index] = value; }

            public int Add(Panel value) => List.Add(value);

            public void AddRange(Panel[] pages) => Array.ForEach(pages, x => this.Add(x));

            public bool Contains(Panel value) => List.Contains(value);

            public int IndexOf(Panel value) => List.IndexOf(value);

            public void Insert(int index, Panel value) => List.Insert(index, value);

            public void Remove(Panel value) => List.Remove(value);

            protected override void OnInsertComplete(int index, object value)
            {
                base.OnInsertComplete(index, value);

                if (panelBook != null)
                {
                    panelBook.PageIndex = index;
                }
            }

            protected override void OnRemoveComplete(int index, object value)
            {
                base.OnRemoveComplete(index, value);

                if (panelBook != null)
                {
                    if (panelBook.PageIndex == index)
                    {
                        if (index < InnerList.Count)
                        {
                            panelBook.PageIndex = index;
                        }
                        else
                        {
                            panelBook.PageIndex = InnerList.Count - 1;
                        }
                    }
                }
            }

        }

        private System.ComponentModel.IContainer components = null;

        protected PanelCollection panelCollection = null;

        public PanelBook()
        {
            InitializeComponent();

            panelCollection = new PanelCollection(this);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }

            base.Dispose(disposing);
        }

        protected void InitializeComponent()
        {
            components = new System.ComponentModel.Container();
        }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public Panel ActivePanel { get; protected set; } = null;

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override bool AutoScroll { get => base.AutoScroll; set => base.AutoScroll = value; }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new Size AutoScrollMargin { get => base.AutoScrollMargin; set => base.AutoScrollMargin = value; }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new Size AutoScrollMinSize { get => base.AutoScrollMinSize; set => base.AutoScrollMinSize = value; }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override Image BackgroundImage { get => base.BackgroundImage; set => base.BackgroundImage = value; }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override ImageLayout BackgroundImageLayout { get => base.BackgroundImageLayout; set => base.BackgroundImageLayout = value; }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new ImeMode ImeMode { get => base.ImeMode; set => base.ImeMode = value; }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override RightToLeft RightToLeft { get => base.RightToLeft; set => base.RightToLeft = value; }

        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public new bool UseWaitCursor { get => base.UseWaitCursor; set => base.UseWaitCursor = value; }

        [Category("Collection")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public PanelCollection Pages => panelCollection;

        [Category("Collection")]
        public int SelectedIndex
        {
            get => (panelCollection.Count <= 0) ? -1 : panelCollection.IndexOf(this.ActivePanel);
            set
            {
                if (panelCollection.Count <= 0) return;
                if (value < 0) return;
                if (value > (panelCollection.Count - 1)) return;
                if (value == this.SelectedIndex) return;

                ActivatePage(value);
            }
        }

        protected internal int PageIndex
        {
            get => panelCollection.IndexOf(this.ActivePanel);
            set
            {
                if (panelCollection.Count <= 0)
                {
                    ActivatePage(-1);
                    return;
                }

                if ((value < -1) || (value >= panelCollection.Count))
                {
                    throw new ArgumentOutOfRangeException("PageIndex", value, "The page index must be between 0 and " + Convert.ToString(panelCollection.Count - 1));
                }

                ActivatePage(value);
            }
        }

        protected internal void ActivatePage(int index)
        {
            if ((panelCollection.Count == 0) && (index >= panelCollection.Count) && (index <= 0))
            {
                return;
            }

            Panel p = (Panel)panelCollection[index];

            ActivatePage(p);
        }

        protected internal void ActivatePage(Panel page)
        {
            if (this.ActivePanel != null)
            {
                if (this.ActivePanel.InvokeRequired)
                {
                    this.ActivePanel.Invoke(new MethodInvoker(() => {
                        this.ActivePanel.Visible = false;
                    }));
                }
                else
                {
                    this.ActivePanel.Visible = false;
                }
            }

            this.ActivePanel = page;
            if (this.ActivePanel != null)
            {
                this.ActivePanel.Parent = this;
                if (!this.Contains(this.ActivePanel))
                {
                    this.Container.Add(this.ActivePanel);
                }

                if (this.ActivePanel.InvokeRequired)
                {
                    this.ActivePanel.Invoke(new MethodInvoker(() => {
                        this.ActivePanel.Dock = DockStyle.Fill;
                        this.ActivePanel.Visible = true;
                        this.ActivePanel.BringToFront();
                    }));
                }
                else
                {
                    this.ActivePanel.Dock = DockStyle.Fill;
                    this.ActivePanel.Visible = true;
                    this.ActivePanel.BringToFront();
                }
            }

            if (this.ActivePanel != null)
            {
                if (this.ActivePanel.InvokeRequired)
                {
                    this.ActivePanel.Invoke(new MethodInvoker(() => {
                        this.ActivePanel.Invalidate();
                    }));
                }
                else
                {
                    this.ActivePanel.Invalidate();
                }
            }
            else
            {
                this.Invalidate();
            }
        }

#if DEBUG

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            if (this.DesignMode)
            {
                this.Invalidate();
            }
        }

#endif

        protected override void DestroyHandle()
        {
            base.DestroyHandle();

            foreach (Panel p in panelCollection)
            {
                p.Dispose();
            }
        }

    }
}