using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Project
{
    /// <summary>
    /// 2017-04-13 13:26:00 : 라벨이므로 커서 IN 시 Hand 에서 Default로 변경함
    /// </summary>
    public partial class CtlPos : Control
    {
        #region "Enum & Structure"
        public enum eColorTheme : byte
        {
            DaeHyun = 0,
            eGrayBlue,
            eDarkBlue,
            TopMenu,
            GrayButton,
            GrayTitleBar,
            IOStatus,
            IOStatusDepp,
            BlackButton,
            RedButton,
            GrayOmokButton,
            Stepbar,
            RobotStatus,
            NewGray_Group,
            NewGray_BG,
            NewGray_Button,
            NewBlue_Button,
            Custom,
        }
        #endregion

        public string[] msg { get; set; }
        public event EventHandler<ItemClickEventArgs> ItemClick;




        //public new event EventHandler Click;
        public CtlPos()
        {
            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.MouseDown += arButton_MouseDown;
            this.MouseUp += arButton_MouseUp;
            this.MouseEnter += arButton_MouseEnter;
            this.MouseLeave += arButton_MouseLeave;
            this.Resize += arLabel_Resize;

            base.BackColor = Color.FromArgb(32, 32, 32);
            ForeColor = Color.White;
        }

        ~CtlPos()
        {
            this.MouseDown -= arButton_MouseDown;
            this.MouseUp -= arButton_MouseUp;
            this.MouseEnter -= arButton_MouseEnter;
            this.MouseLeave -= arButton_MouseLeave;
            this.Resize -= arLabel_Resize;
        }

        public void ClearData()
        {
            foreach (var item in Items)
            {
                item.Direction = '0';
                item.Active = false;
                item.Focus = false;
            }
        }

        public void PerformClick()
        {
            if (Enabled == false) return; //171126
            this.InvokeOnClick(this, new EventArgs());
        }

        void arLabel_Resize(object sender, EventArgs e)
        {
            if (this.MinimumSize.Width == 0 || this.MinimumSize.Height == 0)
                this.MinimumSize = new Size(100, 30);

            bRemakeRect = true;
            Invalidate();
        }

        public new Padding Padding
        {
            get
            {
                return base.Padding;
            }
            set
            {
                base.Padding = value;
                this.Invalidate();
            }
        }

        public Color BorderColor { get; set; }
        private int _itemgap = 0;
        public int ItemGap { get { return _itemgap; } set { _itemgap = value; Invalidate(); } }
        Boolean bRemakeRect = true;
        public item[] Items { get; set; }
        protected override void OnPaint(PaintEventArgs e)
        {
            //Set Optimized Double Buffer to reduce flickering
            e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
            e.Graphics.InterpolationMode = InterpolationMode.High;
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

            if (Items == null) e.Graphics.DrawString("No Item", this.Font, Brushes.Red, 10, 10);
            else
            {
                //영역변경시새로한다
                if (bRemakeRect == true) makeRect();

                //아이템그리기
                var sf = new StringFormat
                {
                    Alignment = StringAlignment.Center,
                    LineAlignment = StringAlignment.Center
                };
                foreach (var item in Items)
                {
                    item.Draw(e.Graphics, this.Font, sf);
                }
            }


            //전체테두리
            e.Graphics.DrawRectangle(new Pen(BorderColor), DisplayRectangle.Left, DisplayRectangle.Top, DisplayRectangle.Width - 1, DisplayRectangle.Height - 1);
        }
        void makeRect()
        {
            var indiheight = (int)(DisplayRectangle.Height * 0.15);
            var fullrect = new Rectangle(
           DisplayRectangle.Left + Padding.Left,
           DisplayRectangle.Top + Padding.Top,
           DisplayRectangle.Width - Padding.Left - Padding.Right,
           DisplayRectangle.Height - Padding.Top - Padding.Bottom - 1 - indiheight);

            var itemCountS = this.Items.Where(t => t.ItemType != itemtype.Hidden && t.ItemType != itemtype.Item).Count();
            var itemCountI = this.Items.Where(t => t.ItemType == itemtype.Item).Count();

            var GapWidth = ItemGap * ((itemCountI + itemCountS) - 1);
            var itemWidthS = (ItemGap * 2); //spacer width
            var itemWidthI = (fullrect.Width - GapWidth - (itemWidthS * itemCountS)) / itemCountI;
            var itemHeight = fullrect.Height;

            var i = 0;
            var x = fullrect.Left;
            foreach (var item in Items)
            {
                if (item.ItemType == itemtype.Hidden) continue;
                if (item.ItemType == itemtype.Spacer)
                {
                    var y = fullrect.Top;
                    var w = (int)itemWidthS;
                    var h = DisplayRectangle.Height - Padding.Top - Padding.Bottom + 3;
                    var rectf = new Rectangle(x, y, w, h);
                    item.fullrect = rectf;
                    item.leftrect = Rectangle.Empty;
                    item.rightrect = Rectangle.Empty;
                    x += w + ItemGap;
                }
                else if (item.ItemType == itemtype.NLimit || item.ItemType == itemtype.PLimit)
                {
                    var y = fullrect.Top;
                    var w = (int)itemWidthS;
                    var h = DisplayRectangle.Height - Padding.Top - Padding.Bottom + 3;
                    var rectf = new Rectangle(x, y, w, h);
                    item.fullrect = rectf;
                    item.leftrect = Rectangle.Empty;
                    item.rightrect = Rectangle.Empty;
                    x += w + ItemGap;
                }
                else if (item.Enable_Direction)
                {
                    //var x = (int)(fullrect.Left + i * itemWidth) + (i * ItemGap);
                    var y = fullrect.Top;
                    var w = (int)itemWidthI;
                    var h = itemHeight;
                    var rectf = new Rectangle(x, y, w, h);
                    item.fullrect = rectf;
                    var indiWidth = (int)((rectf.Width - 4) / 2.0);
                    item.leftrect = new Rectangle(rectf.Left, rectf.Bottom + 4, indiWidth, indiheight);
                    item.rightrect = new Rectangle(rectf.Left + indiWidth + 4, rectf.Bottom + 4, indiWidth, indiheight);
                    x += itemWidthI + ItemGap;
                }
                else
                {
                    //var x = (int)(fullrect.Left + i * itemWidth) + (i * ItemGap);
                    var y = fullrect.Top;
                    var w = (int)itemWidthI;
                    var h = DisplayRectangle.Height - Padding.Top - Padding.Bottom + 3;
                    var rectf = new Rectangle(x, y, w, h);
                    item.fullrect = rectf;
                    item.leftrect = Rectangle.Empty;
                    item.rightrect = Rectangle.Empty;
                    x += itemWidthI + ItemGap;
                }
                i += 1;
            }
            bRemakeRect = false;
        }

        // private int LastPosition = -1;
        //private string LastDir = "";
        //public void SetPositionOut(Boolean value)
        //{
        //    if (LastPosition < 0 || LastPosition >= Items.Length) return;

        //    if (value == true)
        //    {
        //        this.Items[LastPosition].BackColor1 = Color.SkyBlue;
        //        this.Items[LastPosition].BackColor2 = Color.DeepSkyBlue;
        //    }

        //    this.Invalidate();
        //}

        /// <summary>
        /// 지정한 개체를 선택합니다.
        /// </summary>
        /// <param name="idx"></param>
        public void SetPosition(ePosition idx)
        {
      
            foreach (var item in Items)
                item.Focus = false;
            if (idx == ePosition.NONE) return;
            var pos = Items.Where(t => t.Position == idx).First();
            pos.Focus = true;
        }
        public bool GetPositionActive(ePosition idx)
        {
            if (idx == ePosition.NONE) return false;
            var pos = Items.Where(t => t.Position == idx).First();
            return pos.Active;
        }
        public void SetPositionActive(ePosition idx)
        {
        
            foreach (var item in Items)
                item.Active = false;
            if (idx == ePosition.NONE) return;
            var pos = Items.Where(t => t.Position == idx).First();
            pos.Active = true;
        }

        /// <summary>
        /// 활성화된 위치를 모두 초기화 한다
        /// </summary>
        public void SetPositionDeActive()
        {
            foreach (var item in Items)
                item.Active = false;
        }
        public void SetTargetPosition(ePosition idx)
        {
           
            foreach (var item in Items)
                item.Target = false;
            if (idx == ePosition.NONE) return;
            var pos = Items.Where(t => t.Position == idx).First();
            pos.Target = true;
        }
        /// <summary>
        /// 지정한 개체의 left,right 값을 바꿉니다 .rfid값이 변경되었을때 처리합니다. dir=0이면 왼쪽이 켜집니다)
        /// </summary>
        /// <param name="idx"></param>
        /// <param name="dir"></param>
        public void SetDirection(string dir)
        {
            //모든 위치값이 초기화 된다.
            foreach (var item in Items)
                item.Direction = '0';

            var selectitem = this.Items.Where(t => t.Focus).FirstOrDefault();
            if (selectitem != null)
            {
                if (dir.isEmpty()) selectitem.Direction = '0';
                else selectitem.Direction = (dir == "0" ? '1' : '2');
            }
        }

        public enum itemtype
        {
            Hidden,
            NLimit,
            PLimit,
            Spacer,
            Item,
        }

        public class item
        {
            public ePosition Position { get; set; }
            public itemtype ItemType { get; set; }
            //   public bool Hidden { get; set; }
            public bool Enable_Direction { get; set; }

            #region Colorlist
            public Color BackColor2
            {
                get
                {
                    if (Active)
                    {
                        if (ItemType == itemtype.NLimit || ItemType == itemtype.PLimit)
                            return Color.Tomato;
                        else
                            return Color.Lime;
                    }
                    else if (Focus)
                    {
                        if (ItemType == itemtype.NLimit || ItemType == itemtype.PLimit)
                            return Color.Tomato;
                        else
                            return Color.Yellow;
                    }
                    else return Color.FromArgb(82, 82, 82);
                }
            }
            public Color BackColor1
            {
                get
                {
                    if (Active)
                    {
                        if (ItemType == itemtype.NLimit || ItemType == itemtype.PLimit)
                            return Color.Red;
                        else
                            return Color.Green;
                    }
                    else if (Focus)
                    {
                        if (ItemType == itemtype.NLimit || ItemType == itemtype.PLimit)
                            return Color.Red;
                        else
                            return Color.Gold;
                    }
                    else return Color.FromArgb(64, 64, 64);
                }
            }
            public Color ForeColor
            {
                get
                {
                    if (this.Target) return Color.DarkMagenta;
                    else return Color.Black;
                }
            }
            public Color ShadowColor { get { return Color.DimGray; } }
            public Color BorderColor { get { return Color.Black; } }
            public Color RightColor
            {
                get
                {
                    if (Direction == '2')
                    {
                        if (Active) return Color.Lime;
                        else return Color.Gold;
                    }
                    else return Color.Transparent;
                }
            }
            public Color LeftColor
            {
                get
                {
                    if (Direction == '1')
                    {
                        if (Active) return Color.Lime;
                        else return Color.Gold;
                    }
                    else return Color.Transparent;
                }
            }
            #endregion

            [Browsable(false)]
            public Rectangle fullrect { get; set; }
            [Browsable(false)]
            public Rectangle leftrect { get; set; }
            [Browsable(false)]
            public Rectangle rightrect { get; set; }

            public bool Active { get; set; }
            public bool Focus { get; set; }
            public char Direction { get; set; }
            public bool Target { get; set; }

            public string Title { get; set; }

            // public bool Spacer { get; set; }

            public item()
            {
                Position = ePosition.NONE;
                ItemType = itemtype.Item;
                //  Spacer = false;
                fullrect = Rectangle.Empty;
                leftrect = Rectangle.Empty;
                rightrect = Rectangle.Empty;
                Enable_Direction = true;
                Active = false;
                Focus = false;
                Target = false;
                Direction = '0';
                //  Hidden = false;
            }

            public override string ToString()
            {
                if (this.ItemType == itemtype.Hidden)
                    return $"{Title}(숨김)";
                else if (this.ItemType == itemtype.Spacer)
                    return $"(SPACER)";
                else if (this.ItemType == itemtype.NLimit)
                    return $"N-LIMIT";
                else if (this.ItemType == itemtype.PLimit)
                    return $"P-LIMIT";
                else
                    return $"{Title}";
            }

            public void Draw(Graphics g, Font font, StringFormat sf)
            {
                Pen pen_border = null;
                LinearGradientBrush br_back = null;
                SolidBrush br_text = null;

                //배경색

                //펜
                if (pen_border == null) pen_border = new Pen(this.BorderColor);
                else pen_border.Color = this.BorderColor;

                //배경브러쉬
                if (br_back == null) br_back = new LinearGradientBrush(this.fullrect, this.BackColor1, this.BackColor2, LinearGradientMode.Vertical);
                else
                {
                    br_back.LinearColors[0] = this.BackColor1;
                    br_back.LinearColors[1] = this.BackColor2;
                }

                //제목브러쉬
                if (br_text == null) br_text = new SolidBrush(this.ForeColor);
                else br_text.Color = this.ForeColor;

                //배경표시
                g.FillRectangle(br_back, this.fullrect);

                //제목표시
                if (this.Title.isEmpty() == false && this.ItemType == itemtype.Item)
                {
                    if (this.ShadowColor != Color.Transparent && this.ShadowColor != this.ForeColor)
                    {
                        using (var brShadow = new SolidBrush(this.ShadowColor))
                            g.DrawString(
                                this.Title,
                                font, brShadow,
                                new Rectangle(
                                this.fullrect.Left + 1,
                                this.fullrect.Top + 1,
                                this.fullrect.Width,
                                this.fullrect.Height),
                                sf);
                    }

                    g.DrawString(this.Title, font, br_text, this.fullrect, sf);
                    g.DrawString(this.Title, font, br_text, this.fullrect, sf);
                }

                //테두리표시
                g.DrawRectangle(pen_border, this.fullrect);

                if (Enable_Direction)
                {

                    //좌측테두리
                    if (this.leftrect.IsEmpty == false)
                    {
                        if (this.LeftColor != Color.Transparent)
                        {
                            using (SolidBrush sb = new SolidBrush(this.LeftColor))
                                g.FillRectangle(sb, this.leftrect);
                        }
                        g.DrawRectangle(pen_border, this.leftrect);
                    }
                    //우측테두리
                    if (this.rightrect.IsEmpty == false)
                    {
                        if (this.RightColor != Color.Transparent)
                        {
                            using (SolidBrush sb = new SolidBrush(this.RightColor))
                                g.FillRectangle(sb, this.rightrect);
                        }
                        g.DrawRectangle(pen_border, this.rightrect);
                    }

                }

                if (pen_border != null) pen_border.Dispose();
                if (br_back != null) br_back.Dispose();
                if (br_text != null) br_text.Dispose();
            }
        }

        public class ItemClickEventArgs : EventArgs
        {
            public item Item { get; set; }
            public ItemClickEventArgs(item item)
            {
                this.Item = item;
            }
        }

        void arButton_MouseLeave(object sender, EventArgs e)
        {
            //isMouseOver = false;
            this.Cursor = Cursors.Default;
            Invalidate();
        }

        void arButton_MouseEnter(object sender, EventArgs e)
        {
            //isMouseOver = true;
            this.Cursor = Cursors.Hand;
            Invalidate();
        }

        void arButton_MouseUp(object sender, MouseEventArgs e)
        {
            if (!Enabled)
            {
                return;
            }
            //isMouseDown = false;
            Invalidate();
        }


        void arButton_MouseDown(object sender, MouseEventArgs e)
        {
            if (Enabled == false || Enabled == false) return;
            // isMouseDown = true;

            //item fullrect 에서 클릭위치를 찾아야함
            if (Items != null && Items.Length > 0)
            {
                //마우스위치가 아이템에 포함되어있다면
                var focusItem = Items.Where(t => t.fullrect.Contains(e.Location)).FirstOrDefault();
                if (focusItem != null)
                {
                    ItemClick?.Invoke(this, new ItemClickEventArgs(focusItem));
                }
            }
            Invalidate();
        }



    }
}
