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

namespace arFrame.Control
{
    public partial class MotionDisplay : System.Windows.Forms.Control
    {
        private Color[] colorB1 = new Color[] { 
            Color.MediumSeaGreen,
            Color.DeepSkyBlue,
            Color.Tomato,
            Color.Purple, 
            Color.Tomato,
            Color.FromArgb(40,40,40)
        };
        private Color[] colorB2 = new Color[] {
            Color.SeaGreen, 
            Color.SteelBlue, 
            Color.Red, 
            Color.Indigo, 
            Color.Red,
            Color.FromArgb(30,30,30)
        };

        private StringFormat sf = new StringFormat();
        private string[] IndiName = new string[] { "INP","ORG","LIM","HST","ALM","" };
        public MotITem[] Items;
        private int _colcount = 3;
        private int _rowcount = 2;
        private Color _bordercolor = Color.Black;
        private Color _gridcolor = Color.FromArgb(50, 50, 50);
        private int _bordersize = 1;
        private Padding _padding;
        private string _postionformat = "";
        private int _headerHeight = 16;
        private Font _headerfont = new Font("Consolas",7f);

        
        private int itemCount { get { return _colcount * _rowcount; } }
        
        public new Font Font { get { return base.Font; } set { base.Font = value; this.Invalidate(); } }
        public Font HeaderFont { get { return _headerfont; } set { _headerfont = value; this.Invalidate(); } }
        public int HeaderHeight { get { return _headerHeight; } set { _headerHeight = value; RemakeChartRect(); this.Invalidate(); } }
        public new Padding Padding { get { if (_padding == null) return Padding.Empty; else return _padding; } set { _padding = value; RemakeChartRect(); Invalidate(); } }
        public int ColumnCount { get { return _colcount; } set { _colcount = value; ResetArray(); RemakeChartRect(); } }
        public int RowCount { get { return _rowcount; } set { _rowcount = value; ResetArray(); RemakeChartRect(); } }
        public int BorderSize { get { return _bordersize; } set { _bordersize = value; Invalidate(); } }
        public Color BorderColor { get { return _bordercolor; } set { _bordercolor = value; Invalidate(); } }
        public string PositionDisplayFormat { get { return _postionformat; } set { _postionformat = value; Invalidate(); } }
        public Color GridColor { get { return _gridcolor; } set { _gridcolor = value; Invalidate(); } }

        public new Boolean Enabled { get { return base.Enabled; } set { base.Enabled = value; Invalidate(); } }

        public MotionDisplay()
        {
            InitializeComponent();

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

            // Redraw when resized
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            sf.LineAlignment = StringAlignment.Center;
            sf.Alignment = StringAlignment.Center;


            //값과 이름은 외부의 값을 사용한다
            ResetArray();

            if (MinimumSize.Width == 0 || MinimumSize.Height == 0)
                MinimumSize = new Size(100, 50);
        }

        void ResetArray()
        {

        }


        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            RemakeChartRect();
        }

        public void RemakeChartRect()
        {
            if (DisplayRectangle == Rectangle.Empty) return;

            var baseRect = new Rectangle(
                DisplayRectangle.Left + _padding.Left,
                DisplayRectangle.Top + _padding.Top,
                DisplayRectangle.Width - _padding.Left - _padding.Right,
                DisplayRectangle.Height - _padding.Top - _padding.Bottom);

            double x = 0;
            double y = 0;
            double w = baseRect.Width / (_colcount * 1.0);
            double h = baseRect.Height / (_rowcount * 1.0);

            if (this.Items == null || itemCount != this.Items.Length)
            {
                //아이템갯수가 달라졌으므로 다시 갱신해야함
                var item = new MotITem[RowCount * ColumnCount];
                for (int r = 0; r < RowCount; r++)
                {
                    for (int c = 0; c < ColumnCount; c++)
                    {
                        int idx = r * ColumnCount + c;
                        item[idx] = new MotITem(idx);
                        item[idx].Enable = false;
                        item[idx].Padding = new Padding(0, 0, 0, 0);
                        item[idx].TextAlign = ContentAlignment.MiddleCenter;
                        x = baseRect.Left + (c * w);
                        y = baseRect.Top + (r * h);
                        item[idx].rect = new RectangleF((float)x, (float)y, (float)w, (float)h);
                        item[idx].Dirty = true;
                    }
                }

                this.Items = item;
            }
            else
            {
                //아이템의 갯수는 같으므로 좌표값만 변경해준다.
                for (int r = 0; r < RowCount; r++)
                {
                    for (int c = 0; c < ColumnCount; c++)
                    {
                        int idx = r * ColumnCount + c;
                        var item = Items[idx];
                        x = (c * w);
                        y = (r * h);
                        item.rect = new RectangleF((float)x, (float)y, (float)w, (float)h);
                        item.Dirty = true;
                    }
                }
            }
            this.Invalidate();

        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            //배경그리기
            //using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(DisplayRectangle, BackColor, BackColor2On, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
            pe.Graphics.FillRectangle(new SolidBrush(this.BackColor), DisplayRectangle);

            if (Items == null)
            {
                pe.Graphics.DrawString("no items", this.Font, Brushes.Red, 100, 100);
                return;
            }

            var items = Items.OrderBy(t => t.No);
            foreach (var menu in items)
            {
                drawItem(menu.idx, pe.Graphics);
            }

            //테두리 그리기
            if (BorderSize > 0)
            {
                pe.Graphics.DrawRectangle(new Pen(this.BorderColor, BorderSize),
                this.DisplayRectangle.Left,
                this.DisplayRectangle.Top,
                this.DisplayRectangle.Width - 1,
                this.DisplayRectangle.Height - 1);
            }
        }

        private void drawItem(int itemIndex, Graphics g = null)
        {
            if (g == null) g = this.CreateGraphics();
            var item = this.Items[itemIndex];

            // g.DrawString("rect null", this.Font, Brushes.White, 100, 100);

            if (item.rect == RectangleF.Empty) return;

            var rect = item.rect;// rects[i];

            var diplayText = item.Text;

            //byte Value = 0;

            //배경이 투명이 아니라면 그린다.            
            //var bgColor1 = Color.DarkBlue; //BackColor1Off;
            //var bgColor2 = Color.Blue;// BackColor2Off;

            //if (Value != 0 && item.Enable != false)
            //{
            //    //bgColor1 = Value == 1 ? BackColor1On : BackColor1Err;
            //    //bgColor2 = Value == 1 ? BackColor2On : BackColor2Err;
            //}

            //using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(rect, bgColor1, bgColor2, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
            //    g.FillRectangle(sb, rect);

            // if (mouseOverItemIndex == menu.idx)
            //     this.Cursor = Cursors.Hand;
            // else
            //    this.Cursor = Cursors.Arrow;

            //테두리를 그리는 속성과 트기가 설정된 경우에만 표시
            //if (mouseOverItemIndex == i)
            // {
            //    pe.Graphics.DrawRectangle(new Pen(Color.DeepSkyBlue), rect.Left, rect.Top, rect.Width, rect.Height);
            //}
            //else
            {
               // using (var p = new Pen(BorderColor, 1))
               //     g.DrawRectangle(p, rect.Left, rect.Top, rect.Width, rect.Height);
            }

            //총 5개의 인디게이터와 하단에 위치값을 표시하는 영역이 있따.
            //줄 영역은 50%비율로 처리함
            if(item.Dirty)
            {
                //각 영역을 다시 그려줘야한다.
                var indiWidth = rect.Width / 5.0;
               // var indiHeight = rect.Height / 2.0;
                for (int c = 0; c < 5; c++)
                {
                    item.subRect[c] =   new Rectangle((int)(c * indiWidth + item.rect.Left), (int)(item.rect.Top), (int)indiWidth, (int)HeaderHeight);
                }
                item.Dirty = false;

                //위치값을 나타내는 영역
                item.subRect[5] = new Rectangle((int)item.rect.Left, (int)(item.rect.Top + HeaderHeight), (int)rect.Width, (int)rect.Height - HeaderHeight );

            }

            for(int i = 0 ; i < item.subRect.Length;i++)
            {
                var B1 = colorB1[i];
                var B2 = colorB2[i];

                if (i < (item.subRect.Length - 1))  //상태표시칸은 현재 값에 따라서 색상을 달리한다
                {
                    if ( this.Enabled == false || (item.State[i] == false && DesignMode == false))
                    {
                        B1 = Color.FromArgb(20,20,20);
                        B2 = Color.FromArgb(50,50,50);
                    }
                }
                
                var rt = item.subRect[i];
                using (var br = new System.Drawing.Drawing2D.LinearGradientBrush(rt, B1, B2, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
                    g.FillRectangle(br, rt);

               // g.DrawRectangle(Pens.Yellow, rt);
                if (i < (item.subRect.Length-1))
                {
                    sf.Alignment = StringAlignment.Center; 
                    sf.LineAlignment = StringAlignment.Center;
                    g.DrawString(IndiName[i], HeaderFont, Brushes.White, rt, sf);
                }
                else
                {
                    sf.LineAlignment = StringAlignment.Center;
                    sf.Alignment = StringAlignment.Far;
                    g.DrawString(item.Position.ToString(PositionDisplayFormat) + " [" + item.PositionCmd.ToString(PositionDisplayFormat) + "] ", 
                        this.Font,
                        new SolidBrush(item.PositionColor), 
                        rt,
                        sf);
                }
            }

            //테두리선은 우측만 처리한다
            for (int i = 0; i < item.subRect.Length ; i++)
            {
                var rt = item.subRect[i];
                var x1 = rt.Right;
                var y1 = rt.Top;
                var x2 = rt.Right;
                var y2 = rt.Bottom;
                g.DrawLine(new Pen(GridColor), x1, y1, x2, y2);
            }
            var posRect = item.subRect[item.subRect.Length - 1];
            g.DrawLine(new Pen(Color.Black,1), posRect.Left, posRect.Top, posRect.Right, posRect.Top);
            

            //인덱스번호 출력
            if (diplayText != "")
            {
                g.DrawString(string.Format("[{0}] {1}", item.idx, diplayText),
                this.Font, new SolidBrush(this.ForeColor),
                item.rect.Left + 3, item.rect.Top + 3);
            }

          

        }

    }
}
