#if NETFX || NETCORE

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

namespace Apewer.Surface
{

    /// <summary></summary>
    public class BlockButton : BaseControl
    {

        #region definition

        private BlockBox _border = new BlockBox();
        private BlockLabel _caption = new BlockLabel();

        private Color _normaltext = FormsUtility.Black;
        private Color _hovertext = FormsUtility.Black;
        private Color _lockedtext = FormsUtility.GraceLocked;

        #endregion

        #region this

        private void VarInit(string caption)
        {
            this.Controls.Add(_border);
            _border.Controls.Add(_caption);

            this.Size = new Size(120, 40);

            _border.Dock = DockStyle.Fill;
            _border.Padding = new Padding(1, 1, 1, 1);
            _border.HaveBorder = true;

            _caption.Dock = DockStyle.Fill;
            _caption.TextAlign = ContentAlignment.MiddleCenter;
            _caption.Caption = string.IsNullOrEmpty(caption) ? "" : caption;

            UpdateColor();
            EventInit();
        }

        /// <summary>
        /// 
        /// </summary>
        public BlockButton()
        {
            VarInit(this.Name);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="caption"></param>
        public BlockButton(string caption)
        {
            VarInit(caption);
        }

        #endregion

        #region event

        private void EventInit()
        {
            this.LockedChanged += Event_LockedChanged;

            this.MouseMove += Event_This_MouseMove;
            this.MouseLeave += Event_This_MouseLeave;

            {

                _border.MouseClick += Event_Caption_MouseClick;
                _border.MouseDoubleClick += Event_Caption_MouseDoubleClick;
                _border.MouseDown += Event_Caption_MouseDown;
                _border.MouseUp += Event_Caption_MouseUp;
                _border.MouseMove += Event_Border_MouseMove;
                _border.MouseWheel += Event_Caption_MouseWheel;

                _border.Click += Event_Caption_Click;
                _border.DoubleClick += Event_Caption_DoubleClick;
                _border.MouseCaptureChanged += Event_Caption_MouseCaptureChanged;
                _border.MouseEnter += Event_Caption_MouseEnter;
                _border.MouseHover += Event_Caption_MouseHover;
                _border.MouseLeave += Event_Caption_MouseLeave;

                _border.PreviewKeyDown += Event_Caption_PreviewKeyDown;

            }

            {
                _caption.MouseClick += Event_Caption_MouseClick;
                _caption.MouseDoubleClick += Event_Caption_MouseDoubleClick;
                _caption.MouseDown += Event_Caption_MouseDown;
                _caption.MouseUp += Event_Caption_MouseUp;
                _caption.MouseMove += Event_Caption_MouseMove;
                _caption.MouseWheel += Event_Caption_MouseWheel;

                _caption.Click += Event_Caption_Click;
                _caption.DoubleClick += Event_Caption_DoubleClick;
                _caption.MouseCaptureChanged += Event_Caption_MouseCaptureChanged;
                _caption.MouseEnter += Event_Caption_MouseEnter;
                _caption.MouseHover += Event_Caption_MouseHover;
                _caption.MouseLeave += Event_Caption_MouseLeave;

                _caption.PreviewKeyDown += Event_Caption_PreviewKeyDown;

            }
        }

        private void Event_Border_MouseMove(object sender, MouseEventArgs e)
        {
            this.OnMouseMove(e);
        }

        private void Event_This_MouseMove(object sender, EventArgs e)
        {
            Hover = true;
        }

        private void Event_This_MouseLeave(object sender, EventArgs e)
        {
            Hover = false;
        }

        private void Event_LockedChanged(object sender, EventArgs e)
        {
            _caption.ForeColor = Locked ? Color.Gray : NormalText;
            UpdateColor();
        }

        private void Event_Caption_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (!Locked) this.OnPreviewKeyDown(e);
        }

        private void Event_Caption_DoubleClick(object sender, EventArgs e)
        {
            if (!Locked) this.OnDoubleClick(e);
        }

        private void Event_Caption_Click(object sender, EventArgs e)
        {
            if (!Locked) this.OnClick(e);
        }

        private void Event_Caption_MouseWheel(object sender, MouseEventArgs e)
        {
            if (!Locked)
            {
                int voffset = HaveBorder ? 1 : 0;
                this.OnMouseWheel(new MouseEventArgs(e.Button, e.Clicks, e.X + voffset, e.Y + voffset, e.Delta));
            }
        }

        private void Event_Caption_MouseMove(object sender, MouseEventArgs e)
        {
            if (!Locked)
            {
                int voffset = HaveBorder ? 1 : 0;
                this.OnMouseMove(new MouseEventArgs(e.Button, e.Clicks, e.X + voffset, e.Y + voffset, e.Delta));
            }
        }

        private void Event_Caption_MouseLeave(object sender, EventArgs e)
        {
            if (!Locked)
            {
                if (!Locked) this.OnMouseLeave(e);
            }
        }

        private void Event_Caption_MouseHover(object sender, EventArgs e)
        {
            if (!Locked) this.OnMouseHover(e);
        }

        private void Event_Caption_MouseEnter(object sender, EventArgs e)
        {
            if (!Locked) this.OnMouseEnter(e);
        }

        private void Event_Caption_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (!Locked)
            {
                int voffset = HaveBorder ? 1 : 0;
                this.OnMouseDoubleClick(new MouseEventArgs(e.Button, e.Clicks, e.X + voffset, e.Y + voffset, e.Delta));
            }
        }

        private void Event_Caption_MouseCaptureChanged(object sender, EventArgs e)
        {
            if (!Locked) this.OnMouseCaptureChanged(e);
        }

        private void Event_Caption_MouseUp(object sender, MouseEventArgs e)
        {
            if (!Locked)
            {
                int voffset = HaveBorder ? 1 : 0;
                this.OnMouseUp(new MouseEventArgs(e.Button, e.Clicks, e.X + voffset, e.Y + voffset, e.Delta));
            }
        }

        private void Event_Caption_MouseClick(object sender, MouseEventArgs e)
        {
            if (!Locked)
            {
                int voffset = HaveBorder ? 1 : 0;
                this.OnMouseClick(new MouseEventArgs(e.Button, e.Clicks, e.X + voffset, e.Y + voffset, e.Delta));
            }
        }

        private void Event_Caption_MouseDown(object sender, MouseEventArgs e)
        {
            if (!Locked)
            {
                int voffset = HaveBorder ? 1 : 0;
                this.OnMouseDown(new MouseEventArgs(e.Button, e.Clicks, e.X + voffset, e.Y + voffset, e.Delta));
            }
        }

        #endregion

        #region accessor

        /// <summary>
        /// 
        /// </summary>
        public string Caption { get { return _caption.Text; } set { _caption.Text = string.IsNullOrEmpty(value) ? "" : value; } }

        /// <summary>鼠标悬停时的背景颜色。</summary>
        public Color HoverWall { get { return _border.HoverWall; } set { _border.HoverWall = value; UpdateColor(); } }

        /// <summary>鼠标悬停时的文本颜色。</summary>
        public Color HoverText { get { return _hovertext; } set { _hovertext = value; UpdateColor(); } }

        /// <summary>鼠标悬停时的边框颜色。</summary>
        public Color HoverBorder { get { return _border.HoverBorder; } set { _border.HoverBorder = value; UpdateColor(); } }

        /// <summary>默认背景颜色。</summary>
        public Color NormalWall { get { return _border.NormalWall; } set { _border.NormalWall = value; UpdateColor(); } }

        /// <summary>默认文本颜色。</summary>
        public Color NormalText { get { return _normaltext; } set { _normaltext = value; UpdateColor(); } }

        /// <summary>默认边框颜色。</summary>
        public Color NormalBorder { get { return _border.NormalBorder; } set { _border.NormalBorder = value; UpdateColor(); } }

        /// <summary>锁定时的背景颜色。</summary>
        public Color LockedWall { get { return _border.LostWall; } set { _border.LostWall = value; UpdateColor(); } }

        /// <summary>锁定时的文本颜色。</summary>
        public Color LockedText { get { return _lockedtext; } set { _lockedtext = value; UpdateColor(); } }

        /// <summary>锁定时的边框颜色。</summary>
        public Color LockedlBorder { get { return _border.LostBorder; } set { _border.LostBorder = value; UpdateColor(); } }

        /// <summary>包含边框。</summary>
        public bool HaveBorder { get { return _border.HaveBorder; } set { _border.HaveBorder = value; UpdateColor(); } }

        /// <summary>获取 Label 控件。</summary>
        public Label Label { get { return _caption; } }

        /// <summary>文本的对齐方式。</summary>
        public ContentAlignment TextAlign { get { return _caption.TextAlign; } set { _caption.TextAlign = value; } }

        /// <summary>锁定按钮,禁止点击。</summary>
        public new bool Locked
        {
            get { return base.Locked; }
            set { base.Locked = value; if (value) _hover = false; UpdateColor(); }
        }

        /// <summary>文本的外边距。</summary>
        public Padding BodyMargin
        {
            get
            {
                var vmargin = new Padding(_border.Padding.Left + 1, _border.Padding.Top + 1, _border.Padding.Right + 1, _border.Padding.Bottom + 1);
                return vmargin;
            }
            set
            {
                if (value == null) return;
                _border.Padding = new Padding(value.Left - 1, value.Top - 1, value.Right - 1, value.Bottom - 1);
            }
        }

        #endregion

        #region private

        private bool _hover = false;

        private bool Hover
        {
            get { return _hover; }
            set
            {
                if (Locked) return;
                if (_hover != value)
                {
                    _hover = value;
                    UpdateColor();
                }
            }
        }

        private void UpdateColor()
        {
            if (Locked)
            {
                _border.GoLost();
                _caption.ForeColor = _lockedtext;
                _caption.BackColor = _border.LostWall;
            }
            else
            {
                if (_hover)
                {
                    _border.GoHover();
                    _caption.ForeColor = HoverText;
                    _caption.BackColor = _border.HoverWall;
                }
                else
                {
                    _border.GoNormal();
                    _caption.ForeColor = NormalText;
                    _caption.BackColor = _border.NormalWall;
                }
            }
        }

        #endregion

    }
}

#endif