namespace PerpetuumSoft.Widgets
{
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Runtime.CompilerServices;
    using System.Windows.Forms;

    public abstract class ButtonBase : InstrumentationControl, IButtonControl
    {
        private bool _checked = false;
        private ButtonBehaviour behaviour = ButtonBehaviour.Normal;
        private System.Windows.Forms.DialogResult dialogResult = System.Windows.Forms.DialogResult.None;
        private bool highlighted = false;
        private bool pressed = false;

        [Description("Occurs when the Behaviour property changed"), Category("Property Changed")]
        public event EventHandler BehaviourChanged;

        [Description("Occurs when the Checked property changed"), Category("Property Changed")]
        public event EventHandler CheckedChanged;

        [Category("Property Changed"), Description("Occurs when the DialogResult property changed")]
        public event EventHandler DialogResultChanged;

        public ButtonBase()
        {
            base.SetStyle(0x2000, true);
            base.SetStyle(0x10000, true);
            base.SetStyle(2, true);
            base.SetStyle(0x10, true);
            base.SetStyle(0x200, true);
            base.SetStyle(0x800, true);
        }

        protected void DrawSelect(Graphics g)
        {
            if (this.Focused)
            {
                Rectangle rect = this.get_DisplayRectangle();
                rect.Width--;
                rect.Height--;
                Pen pen = new Pen(Color.Black);
                pen.DashStyle = (DashStyle) 2;
                g.DrawRectangle(pen, rect);
            }
        }

        protected override bool IsInputKey(Keys keyData)
        {
            return (base.Enabled && (keyData == Keys.Space));
        }

        protected virtual void OnBehaviourChanged(EventArgs e)
        {
            if (this.BehaviourChanged != null)
            {
                this.BehaviourChanged(this, e);
            }
        }

        protected virtual void OnCheckedChanged(EventArgs e)
        {
            if (this.CheckedChanged != null)
            {
                this.CheckedChanged(this, e);
            }
        }

        protected override void OnClick(EventArgs e)
        {
            if (base.Enabled)
            {
                if (this.Behaviour == ButtonBehaviour.CheckBox)
                {
                    this.Checked = !this.Checked;
                }
                if (this.Behaviour == ButtonBehaviour.RadioButton)
                {
                    this.Checked = true;
                    if (base.Parent != null)
                    {
                        foreach (Control control in base.Parent.Controls)
                        {
                            if ((control != this) && (control is PerpetuumSoft.Widgets.ButtonBase))
                            {
                                (control as PerpetuumSoft.Widgets.ButtonBase).Checked = false;
                            }
                        }
                    }
                }
                try
                {
                    base.OnClick(e);
                }
                catch (Exception exception)
                {
                    this.Pressed = false;
                    throw exception;
                }
            }
        }

        protected virtual void OnDialogResultChanged(EventArgs e)
        {
            if (this.DialogResultChanged != null)
            {
                this.DialogResultChanged(this, e);
            }
        }

        protected override void OnEnter(EventArgs e)
        {
            base.Invalidate();
            base.OnEnter(e);
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (base.Enabled && (e.KeyData == Keys.Space))
            {
                this.Pressed = true;
            }
            base.OnKeyDown(e);
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            if (base.Enabled && (e.KeyData == Keys.Space))
            {
                this.Pressed = false;
                this.OnClick(new EventArgs());
            }
            base.OnKeyDown(e);
        }

        protected override void OnLeave(EventArgs e)
        {
            base.Invalidate();
            base.OnLeave(e);
        }

        protected override void OnMouseDown(MouseEventArgs mevent)
        {
            if (base.TabStop && base.Enabled)
            {
                base.Focus();
            }
            if (mevent.Button == MouseButtons.Left)
            {
                this.Pressed = true;
            }
            base.OnMouseDown(mevent);
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            this.Highlighted = true;
            base.OnMouseEnter(e);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            this.Highlighted = false;
            base.OnMouseLeave(e);
        }

        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            if (mevent.Button == MouseButtons.Left)
            {
                this.Pressed = false;
            }
            base.OnMouseUp(mevent);
        }

        protected override void OnTextChanged(EventArgs e)
        {
            base.Invalidate();
            base.OnTextChanged(e);
        }

        public void PerformClick()
        {
            this.OnClick(new EventArgs());
        }

        void IButtonControl.NotifyDefault(bool value)
        {
        }

        [Description("Button's behaviour type"), Category("Behavior"), DefaultValue(0)]
        public virtual ButtonBehaviour Behaviour
        {
            get
            {
                return this.behaviour;
            }
            set
            {
                if (this.behaviour != value)
                {
                    this.behaviour = value;
                    this.OnBehaviourChanged(new EventArgs());
                }
            }
        }

        [DefaultValue(false), Category("Behavior"), Description("Indicate if the button is checked(pressed)")]
        public bool Checked
        {
            get
            {
                return this._checked;
            }
            set
            {
                if (this._checked != value)
                {
                    this._checked = value;
                    base.Invalidate();
                    this.OnCheckedChanged(new EventArgs());
                }
            }
        }

        [Category("Behavior"), Description("Modal Dialog Result"), DefaultValue(0)]
        public System.Windows.Forms.DialogResult DialogResult
        {
            get
            {
                return this.dialogResult;
            }
            set
            {
                if (this.dialogResult != value)
                {
                    this.dialogResult = value;
                    this.OnDialogResultChanged(new EventArgs());
                }
            }
        }

        protected bool Highlighted
        {
            get
            {
                return (base.Enabled && this.highlighted);
            }
            set
            {
                if (this.highlighted != value)
                {
                    this.highlighted = value;
                    base.Invalidate();
                }
            }
        }

        protected bool Pressed
        {
            get
            {
                if (!this.pressed)
                {
                    return this._checked;
                }
                return true;
            }
            set
            {
                if (this.pressed != value)
                {
                    this.pressed = value;
                    base.Invalidate();
                }
            }
        }
    }
}
