using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Windows.Forms;

namespace AGVControl
{
    public partial class ValueSelect : Control
    {
        public ValueSelect()
        {
            InitializeComponent();

            // Set Optimized Double Buffer to reduce flickering
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);

            // Redraw when resized
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.Resize += arLabel_Resize;
            this.MouseClick += ValueSelect_MouseClick;
            this.MouseEnter += (s1, e1) => { this.Cursor = Cursors.Hand; };
            this.MouseLeave += (s1, e1) => { this.Cursor = Cursors.Default; };
        }

        private void ValueSelect_MouseClick(object sender, MouseEventArgs e)
        {
            //마우스클릭
            if (rectLButton.IsEmpty == false && rectLButton.Contains(e.Location))
            {
                if (SideButtonClickValue != 0.0)
                {
                    var newvalue = this.Value - SideButtonClickValue;
                    if (newvalue < MinValue) newvalue = MinValue;
                    this.Value = newvalue;
                }

                if (ButtonClick != null) ButtonClick(this, new ButtonClickEventArgs(MouseButtons.Left));
            }


            if (rectRButton.IsEmpty == false && rectRButton.Contains(e.Location))
            {
                if (SideButtonClickValue != 0.0)
                {
                    var newvalue = this.Value + SideButtonClickValue;
                    if (newvalue > MaxValue) newvalue = MaxValue;
                    this.Value = newvalue;
                }

                if (ButtonClick != null) ButtonClick(this, new ButtonClickEventArgs(MouseButtons.Right));
            }


            if (rectCButton.IsEmpty == false && rectCButton.Contains(e.Location))
                if (ButtonClick != null) ButtonClick(this, new ButtonClickEventArgs(MouseButtons.Middle));
        }

        private Rectangle rectLButton;
        private Rectangle rectRButton;
        private Rectangle rectCButton;
        private Boolean bMakeRect = true;

        private double _minvalue = 0.0;
        private double _maxvalue = 9999999999.0;
        public double MinValue { get { return _minvalue; } set { _minvalue = value; Invalidate(); } }

        public double MaxValue { get { return _maxvalue; } set { _maxvalue = value; Invalidate(); } }



        private UInt16 _decimalposition = 0;
        private string _buttonwdith = string.Empty;
        private double _value = 0;
        private Color _border = Color.Lime;
        private double buttongabp;
        public double SideButtonClickValue { get { return buttongabp; } set { buttongabp = value; Invalidate(); } }

        private Color _backbutton = Color.White;
        private Color _sidebutto = Color.Black;

        public Color BackColorButton { get { return _backbutton; } set { _backbutton = value; Invalidate(); } }
        public Color ForeColorButton { get { return _sidebutto; } set { _sidebutto = value; Invalidate(); } }



        public Color ColorBorder { get { return _border; } set { _border = value; Invalidate(); } }

        public override string Text
        {
            get => Value.ToString();
            set
            {
                if (double.TryParse(value, out double dblval) == true)
                    this.Value = dblval;
            }
        }

        public double Value
        {
            get { return _value; }
            set
            {
                if (_value != value)
                {
                    //이 값이 범위를 초과했는지 확인
                    if (value < MinValue)
                    {
                        _value = MinValue;
                        //throw new Exception(string.Format("입력값이 컨트롤의 최소값보다 작습니다(입력:{0},최소값:{1})",value,MinValue));
                    }
                    else if (value > MaxValue)
                    {
                        _value = MaxValue;
                        //throw new Exception(string.Format("입력값이 컨트롤의 최대값보다 작습니다(입력:{0},최대값:{1})", value, MaxValue));
                    }
                    else
                    {
                        _value = value;

                    }
                    Invalidate();
                    if (ValueChanged != null) ValueChanged(this, new EventArgs());
                }
            }
        }
        public UInt16 DecimalPosition { get { return _decimalposition; } set { _decimalposition = value; Invalidate(); } }
        public string ButtonWidth { get { return _buttonwdith; } set { _buttonwdith = value; Invalidate(); } }

        private string _nulldisplay = string.Empty;
        public string NullDisplay { get { return _nulldisplay; } set { _nulldisplay = value; Invalidate(); } }

        private Font _sidefont;
        public Font FontSideButton { get { if (_sidefont == null) return this.Font; else return _sidefont; } set { _sidefont = value; Invalidate(); } }

        void arLabel_Resize(object sender, EventArgs e)
        {
            this.bMakeRect = true;
            Invalidate();
        }

        public class ButtonClickEventArgs : EventArgs
        {
            public MouseButtons Button;
            public ButtonClickEventArgs(MouseButtons button)
            {
                this.Button = button;
                // Console.WriteLine("button clickc : " +button.ToString());
            }
        }

        public event EventHandler<ButtonClickEventArgs> ButtonClick;
        public event EventHandler ValueChanged;

        protected override void OnPaint(PaintEventArgs pe)
        {
            //base.OnPaint(pe);
            if (bMakeRect) MakeRect();



            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            sf.Trimming = StringTrimming.None;
            sf.FormatFlags = StringFormatFlags.NoWrap;

            //좌측버튼표시
            if (rectLButton.IsEmpty == false)
            {
                pe.Graphics.FillRectangle(new SolidBrush(BackColorButton), rectLButton);
                pe.Graphics.DrawString("<<", this.FontSideButton, new SolidBrush(this.ForeColorButton), rectLButton, sf);
            }

            if (rectRButton.IsEmpty == false)
            {
                pe.Graphics.FillRectangle(new SolidBrush(BackColorButton), rectRButton);
                pe.Graphics.DrawString(">>", this.FontSideButton, new SolidBrush(this.ForeColorButton), rectRButton, sf);
            }

            //값표시
            string valuestr;
            if (Value == 0.0 && string.IsNullOrEmpty(NullDisplay) == false)
                valuestr = NullDisplay;
            else
                valuestr = Value.ToString("N" + DecimalPosition.ToString());

            pe.Graphics.FillRectangle(new SolidBrush(BackColor), rectCButton);
            pe.Graphics.DrawString(valuestr, this.Font, new SolidBrush(this.ForeColor), rectCButton, sf);
            sf.Dispose();


            //테두리표시
            if (rectLButton.IsEmpty == false)
                pe.Graphics.DrawRectangle(new Pen(ColorBorder), rectLButton);
            if (rectRButton.IsEmpty == false)
                pe.Graphics.DrawRectangle(new Pen(ColorBorder), rectRButton);
            pe.Graphics.DrawRectangle(new Pen(ColorBorder), rectCButton);
        }

        void MakeRect()
        {
            int bWidth;
            if (string.IsNullOrEmpty(ButtonWidth) == false)
            {
                if (ButtonWidth.EndsWith("%"))
                {
                    if (int.TryParse(ButtonWidth.Substring(0, ButtonWidth.Length - 1), out bWidth) == false)
                        bWidth = 0; //숫자로 바꾸는거 실패
                    else bWidth = (int)(this.DisplayRectangle.Width * (bWidth / 100.0));
                }
                else
                {
                    if (int.TryParse(ButtonWidth, out bWidth) == false)
                        bWidth = 0;
                }
            }
            else bWidth = 0;

            if (bWidth > 0)
            {
                int buttongap = 1;
                //각버튼간 2px 간격을 띄운다.
                bWidth = bWidth - buttongap * 2;
                rectLButton = new Rectangle(
                    DisplayRectangle.Left,
                    DisplayRectangle.Top,
                    bWidth,
                    DisplayRectangle.Height - 1);

                rectCButton = new Rectangle(
                    rectLButton.Right + buttongap,
                    DisplayRectangle.Top,
                    DisplayRectangle.Width - rectLButton.Width * 2 - buttongap * 2,
                    DisplayRectangle.Height - 1);

                rectRButton = new Rectangle(
                    rectCButton.Right + buttongap,
                    DisplayRectangle.Top,
                    bWidth - 1,
                    DisplayRectangle.Height - 1);
            }
            else
            {
                rectLButton = Rectangle.Empty;
                rectRButton = Rectangle.Empty;
                rectCButton = new Rectangle(DisplayRectangle.Left,
                    DisplayRectangle.Top,
                    DisplayRectangle.Width - 1,
                    DisplayRectangle.Height - 1);
            }
            bMakeRect = true;
        }
    }
}
