using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;
namespace GlassButton
{
    class glassButton:Button
    {
        public glassButton()
        {
            setButtonStyle();
            draw(_out, _outBottom, _foreOut, 200, 100, 100);
            Font f = new Font("B Mitra", 10f, FontStyle.Bold);
            this.Font = f;
        }


        #region color theme and style
        [DefaultValue(buttonStyle.Classic)]
        public enum buttonStyle
        {
            Glass, Normal, Classic, System
        }
        [DefaultValue(colorTheme.Glass)]
        public enum colorTheme
        {
            Green, Blue, Red, Yellow, Glass
        }

        private buttonStyle _buttonStyle = buttonStyle.Classic;
        public buttonStyle ButtonStyle
        {
            get { return _buttonStyle; }
            set
            {
                _buttonStyle = value;
                setButtonStyle();
            }
        }
        private colorTheme _colorTheme = colorTheme.Glass;
        public colorTheme ColorTheme
        {
            get { return _colorTheme; }
            set
            {
                _colorTheme = value;
                setButtonStyle();
            }
        }
        #endregion

        #region Some override propeties
        [DefaultValue(typeof(Color),"Transparent")]
        public override Color BackColor
        {
            get
            {
                return base.BackColor;
            }
            set
            {
                base.BackColor = value;
            }
        }
        [DefaultValue(typeof(Color),"Black")]
        public override Color ForeColor
        {
            get
            {
                return base.ForeColor;
            }
            set
            {
                base.ForeColor = value;
            }
        }
        [DefaultValue(typeof(Font),"B Mitra,10pt, style=Bold")]
        public override Font Font
        {
            get
            {
                return base.Font;
            }
            set
            {
                base.Font = value;
            }
        }
        #endregion

        #region Define Button Colors
        Color _out = Color.Black;
        Color _outBottom = Color.Green;
        Color _enter = Color.Green;
        Color _enterButtom = Color.LimeGreen;
        Color _on = Color.Green;
        Color _onBottom = Color.GreenYellow;
        Color _down = Color.DarkGreen;
        Color _downBottom = Color.Green;
        Color _disable = Color.Gray;
        //----------------------------
        Color _foreOut = Color.White;
        Color _foreEnter = Color.Black;
        Color _foreOn = Color.Black;
        Color _foreDown = Color.White;
        Color _foreDisable = Color.LightGray;
        #endregion
        
        private void setButtonStyle()
        {
            switch (_colorTheme)
            {
                case colorTheme.Green:
                    _out = Color.DarkGray;
                    _outBottom = Color.LightGray;
                    _on = _enter = _downBottom = Color.Green;
                    _onBottom = Color.GreenYellow;
                    _down = Color.DarkGreen;
                    _enterButtom = Color.FromArgb(150, 200, 50);
                    _disable = Color.Gray;
                    _foreDisable = Color.DimGray;
                    _foreDown = Color.White;
                    _foreEnter = _foreOn = _foreOut = Color.Black;
                    break;
                case colorTheme.Blue:
                    _out = Color.DarkGray;
                    _outBottom = Color.LightGray;
                    _on = _enter = _downBottom = Color.Blue;
                    _onBottom = Color.Cyan;
                    _down = Color.DarkBlue;
                    _enterButtom = Color.DarkCyan;
                    _disable = Color.Gray;
                    _foreDisable = Color.DimGray;
                    _foreDown = Color.White;
                    _foreEnter = Color.White;
                    _foreOut = _foreOn = Color.Black;
                    break;
                case colorTheme.Red:
                    _out = Color.DarkGray;
                    _outBottom = Color.LightGray;
                    _on = _enter = _downBottom = Color.Red;
                    _onBottom = Color.Pink;
                    _down = Color.DarkRed;
                    _enterButtom = Color.Red;
                    _disable = Color.Gray;
                    _foreDisable = Color.DimGray;
                    _foreDown = Color.White;
                    _foreEnter = Color.White;
                    _foreOn = _foreOut = Color.Black;
                    break;
                case colorTheme.Yellow:
                    _out = Color.DarkGray;
                    _outBottom = Color.LightGray;
                    _on = _enter = _downBottom = Color.Orange;
                    _onBottom = Color.Yellow;
                    _down = Color.Orange;
                    _enterButtom = Color.Gold;
                    _disable = Color.Gray;
                    _foreDisable = Color.DimGray;
                    _foreDown = Color.White;
                    _foreEnter = _foreOn = _foreOut = Color.Black;
                    break;
                case colorTheme.Glass:
                    _out = Color.FromArgb(80, Color.Gray);
                    _outBottom = Color.FromArgb(10, _downBottom);
                    _on = _enter = _downBottom = _out;
                    _onBottom = _out;
                    _down = _out;
                    _enterButtom = _out;
                    _disable = _out;
                    _foreDisable = Color.DimGray;
                    _foreDown = Color.White;
                    _foreEnter = _foreOn = _foreOut = Color.Black;
                    break;
            }
            if (_buttonStyle == buttonStyle.Glass)
            {
                _out = Color.FromArgb(80, Color.Gray);
                _outBottom = Color.FromArgb(10, _downBottom);
            }
            draw(_out, _outBottom, _foreOut, 200, 100, 100);
        }


        private void draw(Color bgColor, Color bgColorButtom, Color foreColor, int topAlpha, int middleAlpha, int buttomAlpha)
        {
            if (_buttonStyle == buttonStyle.System)
            {
                this.FlatStyle = FlatStyle.Standard;
                this.FlatAppearance.BorderSize = 0;
                this.BackgroundImage = null;
                this.BackColor = Color.FromKnownColor(KnownColor.Control);
                this.UseVisualStyleBackColor = true;
                return;
            }
            else if (_buttonStyle == buttonStyle.Classic)
            {
                this.BackColor = Color.Transparent;
                this.FlatStyle = FlatStyle.Flat;
                this.BackgroundImage = null;
                this.FlatAppearance.MouseOverBackColor = _on;
                this.FlatAppearance.MouseDownBackColor = _down;
                this.FlatAppearance.BorderSize = 1;
                this.FlatAppearance.BorderColor = Color.DimGray;
                this.BackColor = Color.Transparent;
                this.UseVisualStyleBackColor = false;
                return;
            }
            else
            {
                this.UseVisualStyleBackColor = false;
                this.BackColor = Color.Transparent;
                this.FlatStyle = FlatStyle.Flat;
                this.FlatAppearance.BorderSize = 0;
                this.FlatAppearance.MouseDownBackColor = this.FlatAppearance.MouseOverBackColor = this.BackColor = Color.Transparent;
                //this.FlatAppearance.BorderColor = null;
            }
            int x = this.Width, y = this.Height;
            Bitmap bg = new Bitmap(x, y);
            Graphics gr = Graphics.FromImage(bg);
            Rectangle rec = new Rectangle(0, 0, x, y);
            Rectangle recTop = new Rectangle(0, 0, x, y / 2);
            Rectangle recBottom = new Rectangle(0, (int)(y * 0.6f), x, (int)(y * 0.4f));
            GraphicsPath gp = new GraphicsPath(FillMode.Alternate);
            LinearGradientBrush brTopReflect = new LinearGradientBrush(recTop, Color.FromArgb(topAlpha, Color.White), Color.FromArgb(middleAlpha, Color.White), LinearGradientMode.Vertical);
            //LinearGradientBrush brButtomReflect = new LinearGradientBrush(recButtom, Color.FromArgb(0, Color.White), Color.FromArgb(buttomAlpha, Color.White), LinearGradientMode.Vertical);
            LinearGradientBrush brush = new LinearGradientBrush(rec, bgColor, bgColorButtom, LinearGradientMode.Vertical);

            gp.Reset();
            // fill BG
            gp.AddLine(0, 1, 1, 1);//topLeft
            gp.AddLine(1, 1, 1, 0);//topLeft
            gp.AddLine(1, 0, x - 2, 0);//top
            gp.AddLine(x - 2, 0, x - 2, 1);//topRight
            gp.AddLine(x - 2, 1, x - 1, 1);//topRight
            gp.AddLine(x - 1, 1, x - 1, y - 2);//right
            gp.AddLine(x - 1, y - 2, x - 2, y - 2);//ButtomRight
            gp.AddLine(x - 2, y - 2, x - 2, y - 1);//buttomRight
            gp.AddLine(x - 2, y - 1, 1, y - 1);//buttom
            gp.AddLine(1, y - 1, 1, y - 2);//ButtomLeft
            gp.AddLine(1, y - 2, 0, y - 2);//buttomLeft
            gp.AddLine(0, y - 2, 0, 1);//left
            gr.FillPath(brush, gp);

            gp.Reset();
            //Border
            gp.AddLine(1, 2, 2, 2);//topLeft
            gp.AddLine(2, 2, 2, 1);//topLeft
            gp.AddLine(2, 1, x - 3, 1);//top
            gp.AddLine(x - 4, 1, x - 4, 2);//topRight
            gp.AddLine(x - 4, 2, x - 3, 2);//topRight
            gp.AddLine(x - 3, 2, x - 3, y - 3);//right
            gp.AddLine(x - 3, y - 3, x - 4, y - 3);//BottomRight
            gp.AddLine(x - 4, y - 3, x - 3, y - 3);//bottomRight
            gp.AddLine(x - 3, y - 3, 2, y - 3);//bottom
            gp.AddLine(2, y - 3, 2, y - 4);//BottomLeft
            gp.AddLine(2, y - 4, 1, y - 4);//bottomLeft
            gp.AddLine(1, y - 4, 1, 1);//left
            Pen pen = new Pen(Color.FromArgb(70, Color.White));
            if (_buttonStyle == buttonStyle.Glass)
                pen.Color = Color.FromArgb(70, Color.Black);
            gr.DrawPath(pen, gp);

            gp.Reset();
            //Top Reflect
            gp.AddLine(1, 2, 2, 2);//topLeft
            gp.AddLine(2, 2, 2, 1);//topLeft
            gp.AddLine(2, 1, x - 3, 1);//top
            gp.AddLine(x - 3, 1, x - 3, 2);//topRight
            gp.AddLine(x - 3, 2, x - 2, 2);//topRight
            gp.AddLine(x - 2, 2, x - 2, y / 2);//right
            gp.AddLine(x - 3, y / 2, 2, y / 2);//bottom
            gp.AddLine(1, y / 2, 1, 2);//left
            gr.FillPath(brTopReflect, gp);

            gp.Reset();// y - y / 3
            //bottom Reflect
            gp.AddBezier(1, y * 0.7f, x * 0.16f, y * 0.65f, x * 0.32f, y * 0.6f, x * 0.5f, y * 0.4f);//top arc left
            gp.AddBezier(x * 0.5f, y * 0.4f, x * 0.66f, y * 0.6f, x * 0.82f, y * 0.65f, x - 2, y * 0.7f);//top arc right
            gp.AddLine(x - 2, y - 3, x - 3, y - 3);//BottomRight
            gp.AddLine(x - 3, y - 3, x - 3, y - 2);//bottomRight
            gp.AddLine(x - 2, y - 2, 3, y - 2);//bottom
            gp.AddLine(2, y - 2, 2, y - 3);//BottomLeft
            gp.AddLine(2, y - 3, 1, y - 2);//bottomLeft
            PathGradientBrush brpath = new PathGradientBrush(gp);
            brpath.CenterColor = Color.FromArgb(buttomAlpha, Color.White);
            brpath.CenterPoint = new PointF(x * 0.5f, y - 2);
            brpath.SurroundColors = new Color[] { Color.FromArgb(0, Color.White) };
            gr.FillPath(brpath, gp);

            if (this.BackgroundImage != null)
            {
                this.BackgroundImage.Dispose();
            }
            this.BackgroundImage = bg;
            this.ForeColor = foreColor;
            brpath.Dispose();
            pen.Dispose();
            gr.Dispose();
            gp.Dispose();
            brTopReflect.Dispose();
            brush.Dispose();
        }



        protected override void OnMouseEnter(System.EventArgs e)
        {
            draw(_on, _onBottom, _foreOn, 235, 140, 200);
            base.OnMouseEnter(e);
        }

        protected override void OnResize(System.EventArgs e)
        {
            if (!this.Focused)
                draw(_out, _outBottom, _foreOut, 200, 100, 100);
            else
                draw(_enter, _enterButtom, _foreEnter, 230, 130, 150);
            base.OnResize(e);
        }

        protected override void OnMouseLeave(System.EventArgs e)
        {
            if (!Focused)
                draw(_out, _outBottom, _foreOut, 200, 100, 100);
            else
                draw(_enter, _enterButtom, _foreEnter, 230, 130, 150);
            base.OnMouseLeave(e);
        }

        protected override void OnMouseDown(MouseEventArgs mevent)
        {
            draw(_down, _downBottom, _foreDown, 80, 20, 100);
            base.OnMouseDown(mevent);
        }

        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            draw(_on, _onBottom, _foreOn, 230, 130, 200);
            base.OnMouseUp(mevent);
        }

        protected override void OnEnabledChanged(System.EventArgs e)
        {
            if (this.Enabled == true)
                draw(_out, _onBottom, _foreOut, 200, 100, 100);
            else
                draw(_disable, _disable, _foreDisable, 200, 100, 0);
            base.OnEnabledChanged(e);
        }


        protected override void OnKeyDown(KeyEventArgs kevent)
        {
            if (kevent.KeyData == Keys.Space)
                draw(_down, _downBottom, _foreDown, 80, 20, 50);
            base.OnKeyDown(kevent);
        }

        protected override void OnKeyUp(KeyEventArgs kevent)
        {
            if (kevent.KeyData == Keys.Space)
            {
                draw(_enter, _enterButtom, _foreEnter, 230, 130, 50);
            }
            base.OnKeyUp(kevent);
        }

        protected override void OnLeave(System.EventArgs e)
        {
            draw(_out, _outBottom, _foreOut, 200, 100, 50);
            base.OnLeave(e);
        }

        protected override void OnEnter(System.EventArgs e)
        {
            draw(_enter, _enterButtom, _foreEnter, 230, 130, 50);
            base.OnEnter(e);
        }



    }
}