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;
using COMM;
using System.Diagnostics;
using AR;

namespace Project
{
    /// <summary>
    /// 2017-04-13 13:26:00 : 라벨이므로 커서 IN 시 Hand 에서 Default로 변경함
    /// </summary>
    public partial class CtlAuto : 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 arDev.BMS dev_bms { private get; set; } = null;
       // public arDev.FakePLC dev_plc { private get; set; } = null;
        public arDev.Narumi dev_agv { private get; set; } = null;
        public Device.Xbee dev_xbe { private get; set; } = null;

        public event EventHandler<ItemClickEventArgs> ItemClick;

        private Font _font_bms_vlt = new Font("Consolas", 50, FontStyle.Bold);
        private Font _font_bms_lev = new Font("Consolas", 150, FontStyle.Bold);
        private Font _font_main_batlev = new Font("Consolas", 50, FontStyle.Bold);
        public Font Font_MAIN_BMSLevel { get { return _font_main_batlev; } set { _font_main_batlev = value; Invalidate(); } }
        public Font Font_BMS_Volt { get { return _font_bms_vlt; } set { _font_bms_vlt = value; Invalidate(); } }
        public Font Font_BMS_Level { get { return _font_bms_lev; } set { _font_bms_lev = value; Invalidate(); } }

        public enum eScean
        {
            Normal = 0,
            Progress,
        }
        public eScean Scean { get; set; } = eScean.Normal;

        //public new event EventHandler Click;
        public string StatusMessage { get; set; } = string.Empty;
        public CtlAuto()
        {

            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;
        }

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

        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; }

        public StateMachine.ERunStep runStep = StateMachine.ERunStep.READY;
        public Boolean OnUpdateMode = false;

        public Boolean Status_AutoRun
        {
            get
            {
                if (VAR.BOOL == null) return true;
                else return VAR.BOOL[eVarBool.FLAG_AUTORUN];
            }
        }



        public DateTime StopTime { get; set; }
        private string stopmessage = "";
        public string StopMessage { get { return stopmessage; } set { this.stopmessage = value; this.Invalidate(); } }

        System.Diagnostics.Stopwatch wframe = new System.Diagnostics.Stopwatch();

        Point centerpt;
        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 (wframe.IsRunning == false) wframe.Restart();

            if (this.Scean == eScean.Normal)
            {
                var chargeM = VAR.BOOL?.Get(eVarBool.FLAG_CHARGEONM) ?? false;
                var chargeA = dev_agv?.system1.Battery_charging ?? false;
                var charge = chargeM || chargeA;

                //if (DesignMode) charge = true;
                if (charge)
                {
                    Scean_Normal_Charge(e.Graphics, (chargeM ? "수동" : "자동"));
                }
                else
                {
                    Scean_Normal(e.Graphics);
                }
            }
            else if (this.Scean == eScean.Progress)
                Scean_Progress(e.Graphics);

            //버젼표시
            var version = VAR.STR?.Get(eVarString.SWVersion) ?? string.Empty;
            if (DesignMode) version = "1.1.1.1";
            using (var f = new Font("Consolas", 8))
                e.Graphics.DrawString(version, f, Brushes.Gray, DisplayRectangle, sfBottomRight);

        }
        StringFormat sfEnd = new StringFormat
        {
            Alignment = StringAlignment.Far,
            LineAlignment = StringAlignment.Center
        };
        StringFormat sfStart = new StringFormat
        {
            Alignment = StringAlignment.Near,
            LineAlignment = StringAlignment.Center
        };
        StringFormat sfCenter = new StringFormat
        {
            Alignment = StringAlignment.Center,
            LineAlignment = StringAlignment.Center
        };
        StringFormat sfBottom = new StringFormat
        {
            Alignment = StringAlignment.Center,
            LineAlignment = StringAlignment.Far
        };
        StringFormat sfBottomRight = new StringFormat
        {
            Alignment = StringAlignment.Far,
            LineAlignment = StringAlignment.Far
        };
        StringFormat sfBottomLeft = new StringFormat
        {
            Alignment = StringAlignment.Near,
            LineAlignment = StringAlignment.Far
        };
        public float ProgressMax { get; set; } = 100;
        public float ProgressVal { get; set; } = 0;
        Matrix TranslationTransform = new Matrix();
        Matrix RotateTransform = new Matrix();
        void Scean_Progress(Graphics g)
        {
            var progheight = DisplayRectangle.Height * 0.1f;
            var r = new RectangleF(DisplayRectangle.Left + 50,
                DisplayRectangle.Bottom - progheight - (DisplayRectangle.Height * 0.2f),
                DisplayRectangle.Width - 100, progheight);

            var rt = new RectangleF(
                r.Left,
                DisplayRectangle.Top,
                r.Width,
                 r.Top - DisplayRectangle.Height * 0.05f);

            //g.DrawRectangle(Pens.Blue, rt.Left, rt.Top, rt.Width, rt.Height);
            g.DrawString(this.StatusMessage, this.Font, Brushes.White,
              rt, sfBottom);

            var progw = r.Width * (this.ProgressVal / this.ProgressMax);
            var progr = new RectangleF(r.Left, r.Top, progw, r.Height);

            g.FillRectangle(new LinearGradientBrush(r, Color.LightSkyBlue, Color.DeepSkyBlue, LinearGradientMode.Vertical), progr);
            g.DrawRectangle(Pens.DimGray, r.Left, r.Top, r.Width, r.Height);

        }
        int textdir = -1;
        void Scean_Normal_Charge(Graphics g, string mode)
        {
            var bmsready = dev_bms?.IsValid ?? false;// != null;

            if (DesignMode) bmsready = true;
            if (bmsready == false)
            {
                var pts = new List<Point>();
                pts.Add(new Point(0, 0));
                pts.Add(new Point(80, 0));
                pts.Add(new Point(0, 80));

                using (var f = new Font("Consolas", 110, FontStyle.Bold))
                    g.DrawString("BMS NOT CONNECTED", f, Brushes.Gold, this.DisplayRectangle, this.sfCenter);

                g.FillPolygon(Brushes.Gold, pts.ToArray());

                pts.Clear();
                pts.Add(new Point(0, 0));
                pts.Add(new Point(30, 0));
                pts.Add(new Point(0, 30));
                g.FillPolygon(Brushes.Orange, pts.ToArray());

            }
            else
            {
                //단순 수치값을 크게 표시히낟.
                var Volt = dev_bms?.BMSInformation.packVoltage ?? 25.35f;
                var Lev = dev_bms?.BMSInformation.rsoc ?? 80f;

                var textColor = Color.Lime;
                if (Lev < 30) textColor = Color.Red;
                else if (Lev < 40) textColor = Color.Tomato;
                else if (Lev < 60) textColor = Color.Orange;
                else if (Lev < 80) textColor = Color.Gold;


                using (var textbrush = new SolidBrush(textColor))
                    g.DrawString($"{Lev:N1}%", this.Font_BMS_Level, textbrush, DisplayRectangle, sfCenter);

                g.DrawString($"{Volt:N1}v", this.Font_BMS_Volt, Brushes.Gold, DisplayRectangle, sfBottomRight);

                var r = new RectangleF(DisplayRectangle.Left, DisplayRectangle.Top,
                    DisplayRectangle.Width, 25);

                //msg = wframe.ElapsedMilliseconds.ToString() + msg;
                var msgc = mode.Equals("수동") ? Color.Gray : Color.Gray;
                using (var f = new Font("맑은 고딕", 11, FontStyle.Regular))
                using (var sb = new SolidBrush(msgc))
                {
                    var msg = mode.Equals("수동") ? "수동 충전 중입니다 / 해제 하려면 케이블을 제거하고 [충전취소] 버튼을 누르세요" :
                 "자동 충전 중 입니다 / 최대 충전량에 도달 하거나 (CALL)이 발생하면 자동 해제 됩니다";

                    var textsize = g.MeasureString(msg, f);
                    //msg = textsize.Width.ToString() + "_" + TranslationTransform.OffsetX.ToString() + ":" + msg;
                    //var minx = DisplayRectangle.Width - textsize.Width

                    //화면이 넘어갔다면 다시 오른쪽으로 간다
                    if (textdir < 0 && TranslationTransform.OffsetX < (textsize.Width - DisplayRectangle.Width))
                        textdir *= -1;
                    else if (textdir > 0 && TranslationTransform.OffsetX >= 0)
                        textdir *= -1;

                    //g.FillRectangle(Brushes.BlanchedAlmond, r.Left, r.Top, r.Width, r.Height);
                    TranslationTransform.Translate(textdir * (wframe.ElapsedMilliseconds / 10f), 0);
                    wframe.Restart();

                    g.Transform = TranslationTransform;

                    g.DrawString(msg, f, sb, r, sfEnd);
                }


                //TranslationTransform.Reset();




            }
        }
        void Scean_Normal(Graphics g)
        {

            // if (Status_AutoRun)
            //   g.FillRectangle(new SolidBrush(Color.FromArgb(40, 40, 40)), this.DisplayRectangle);
            //else
            g.FillRectangle(new SolidBrush(Color.FromArgb(32, 32, 32)), this.DisplayRectangle);

            var wheelSize = new Size((int)(DisplayRectangle.Width * 0.35),
            (int)(DisplayRectangle.Width * 0.35));

            bool agv_run = true;
            if (dev_agv != null) agv_run = dev_agv.system1.agv_run;

            Color wheelbackL = agv_run ? Color.DeepSkyBlue : Color.DimGray;
            Color wheelBorder = Color.Gold;
            if (dev_agv != null)
            {
                if (dev_agv.data.Speed == 'H') wheelBorder = Color.Red;
                else if (dev_agv.data.Speed == 'M') wheelBorder = Color.Gold;
                else if (dev_agv.data.Speed == 'L') wheelBorder = Color.Black;
                else if (dev_agv.data.Speed == 'S') wheelBorder = Color.Magenta;
            }

            var wheelspace = 0;
            var wheelborder = 8;

            //충전중 아이콘 추가
            //var charge = VAR.BOOL?.Get(eVarBool.FLAG_CHARGEONA) ?? false;
            ////charge = true;
            //if (charge)
            //{
            //    var x = DisplayRectangle.Right - Properties.Resources.ChargeH.Width - 20;
            //    var y = -30;
            //    g.DrawImage(Properties.Resources.ChargeH, x, y);
            //}

            //왼쪽오른쪽 분리해서 좌측에는 주행정보를 우측에는 배터리 정보를 표시한다

            //left wheeel
            centerpt = new Point(
                (int)(DisplayRectangle.Width / 2.0),
                (int)(DisplayRectangle.Height / 2.0));

            var rectL = new Rectangle(DisplayRectangle.Left, DisplayRectangle.Top,
                (int)(DisplayRectangle.Width / 2f), DisplayRectangle.Height);
            var rectR = new Rectangle(rectL.Right, DisplayRectangle.Top,
               (int)(DisplayRectangle.Width / 2f), DisplayRectangle.Height);

            wheelSize = new Size((int)(rectL.Width * 0.7f), (int)(rectL.Width * 0.7f));
            var rect_lwheel = new Rectangle(
                (int)(rectL.Left + (rectL.Width - wheelSize.Width) / 2f),
             (int)(rectL.Top + (rectL.Height - wheelSize.Height) / 2f),
                wheelSize.Width,
                wheelSize.Height);

            g.FillEllipse(new SolidBrush(Color.FromArgb(200, wheelbackL)), rect_lwheel);
            g.DrawEllipse(new Pen(Color.Black, wheelborder), rect_lwheel.AddOffset(1, 1));
            g.DrawEllipse(new Pen(wheelBorder, wheelborder), rect_lwheel);


            //g.DrawRectangle(Pens.Red, rectL);
            //g.DrawRectangle(Pens.Blue, rectR);

            //wheel speed text
            string speedchar = "마크\n멈춤";
            if (dev_bms != null)
            {
                //speedchar = dev_bms.Current_Level.ToString("N0");
                if (dev_agv.data.Speed == 'H')
                    speedchar = "고속";
                else if (dev_agv.data.Speed == 'L')
                    speedchar = "저속";
                else if (dev_agv.data.Speed == 'M')
                    speedchar = "중속";
                else if (dev_agv.data.Speed == 'S')
                    speedchar = "마크\n멈춤";
                else
                    speedchar = dev_agv.data.Speed.ToString();
            }

            //g.FillRectangle(Brushes.BlanchedAlmond, r.Left, r.Top, r.Width, r.Height);
            var degree = 10;// wframe.ElapsedMilliseconds / 10f;
                            //var angle = (float)(degree * Math.PI / 180f);

            if (RotateTransform.OffsetX == 0)
            {
                RotateTransform.Translate(DisplayRectangle.Width / 2f, DisplayRectangle.Height / 2f);
            }
            g.Transform = RotateTransform;
            //g.FillEllipse(Brushes.Magenta, new Rectangle(-5, -5, 10, 10));

            RotateTransform.Reset();
            g.Transform = RotateTransform;

            //speedchar = "100";
            using (Font f = new Font("맑은 고딕", 70, FontStyle.Bold))
                g.DrawString(speedchar, f, Brushes.Black, rect_lwheel, sfCenter);


            //배터리모양표시
            List<PointF> batpts = new List<PointF>();
            var batw = (int)(rectR.Width * 0.6f);
            var bath = (int)(rectR.Height * 0.7f);
            var ptLT = new PointF(rectR.Left + (rectR.Width - batw) / 2f, rectR.Top + ((rectR.Height - bath) / 2f) + (rectR.Height * 0.05f));
            batpts.Add(ptLT);
            batpts.Add(new PointF(ptLT.X + batw, ptLT.Y));
            batpts.Add(new PointF(ptLT.X + batw, ptLT.Y + bath));
            batpts.Add(new PointF(ptLT.X, ptLT.Y + bath));
            //g.DrawPolygon(Pens.Gold, batpts.ToArray());


            var bmslevel = 28f;
            if (dev_bms != null) bmslevel = dev_bms.BMSInformation.rsoc;
            var CornerRadius = 10;
            var XPosition = rectR.Left + (rectR.Width - batw) / 2f;
            var YPosition = rectR.Top + (rectR.Height - bath) / 2f + (rectR.Height * 0.05f);
            var batrect = new RectangleF(XPosition, YPosition, batw, bath);
            var bathatsizeH = 30;
            Color bmsback = Color.Lime;
            if (bmslevel < 30) bmsback = Color.Red;
            else if (bmslevel < 40) bmsback = Color.Tomato;
            else if (bmslevel < 70) bmsback = Color.Gold;
            
            using (GraphicsPath Path = new GraphicsPath())
            {
                Path.AddLine(XPosition + CornerRadius, YPosition, XPosition + batw / 2f - (batw * 0.1f), YPosition);
                Path.AddLine(XPosition + batw / 2f - (batw * 0.1f), YPosition, XPosition + batw / 2f - (batw * 0.1f), YPosition - bathatsizeH + CornerRadius);
                Path.AddLine(XPosition + batw / 2f - (batw * 0.1f) + CornerRadius, YPosition - bathatsizeH, XPosition + batw / 2f + (batw * 0.1f) - CornerRadius , YPosition - bathatsizeH);
                Path.AddLine(XPosition + batw / 2f + (batw * 0.1f), YPosition - bathatsizeH + CornerRadius, XPosition + batw / 2f + (batw * 0.1f), YPosition );
                Path.AddLine(XPosition + batw / 2f - (batw * 0.1f), YPosition, XPosition + batw - (CornerRadius * 2), YPosition);
                Path.AddArc(XPosition + batw - (CornerRadius * 2), YPosition, CornerRadius * 2, CornerRadius * 2, 270, 90);
                Path.AddLine(XPosition + batw, YPosition + CornerRadius, XPosition + batw, YPosition + bath - (CornerRadius * 2));
                Path.AddArc(XPosition + batw - (CornerRadius * 2), YPosition + bath - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 0, 90);
                Path.AddLine(XPosition + batw - (CornerRadius * 2), YPosition + bath, XPosition + CornerRadius, YPosition + bath);
                Path.AddArc(XPosition, YPosition + bath - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 90, 90);
                Path.AddLine(XPosition, YPosition + bath - (CornerRadius * 2), XPosition, YPosition + CornerRadius);
                Path.AddArc(XPosition, YPosition, CornerRadius * 2, CornerRadius * 2, 180, 90);
                Path.CloseFigure();
                var tRegion = new System.Drawing.Region(Path);
                var bmsh = (int)(bath * (bmslevel / 100f));
                var gRegion = new Region(new RectangleF(XPosition, YPosition + bath - bmsh, batw, bmsh));
                gRegion.Intersect(tRegion);
                g.DrawPath(new Pen(bmsback, 20), Path);
                g.FillRegion(Brushes.WhiteSmoke, tRegion);
                g.FillRegion(new SolidBrush(bmsback), gRegion);
                g.DrawString($"{bmslevel:N0}", Font_MAIN_BMSLevel, Brushes.Black, batrect, sfCenter);
            }

            this.DrawDirection(g, rect_lwheel, wheelborder);

            //경고메세지표시
            DrawWarning(g);

            //전체테두리
            g.DrawRectangle(new Pen(BorderColor), DisplayRectangle.Left, DisplayRectangle.Top, DisplayRectangle.Width - 1, DisplayRectangle.Height - 1);

            var nextstop = PUB.AGV.data.Speed == 'S';// VAR.BOOL?.Get(eVarBool.NEXTSTOP_MARK) ?? false;
            //if (VAR.BOOL != null) nextstop = VAR.BOOL[eVarBool.NEXTSTOP_MARK];
            //상태메세지표시
            string stmsg = string.Empty;

            if (VAR.STR != null && VAR.STR[eVarString.StatusMessage].isEmpty() == false) stmsg = VAR.STR[eVarString.StatusMessage];
            else stmsg = "STATUS MESSAGE DEMO";
            if (nextstop) stmsg += "|MARK-STOP";

            var MsgColor = Color.Lime;
            if (PUB.Result != null) MsgColor = PUB.Result.SMSG_ForeColor;
            using (SolidBrush sb = new SolidBrush(MsgColor))
            using (Font f = new Font("맑은 고딕", 10, FontStyle.Bold))
                g.DrawString(stmsg, f, sb, DisplayRectangle, new StringFormat
                {
                    Alignment = StringAlignment.Near,
                    LineAlignment = StringAlignment.Far,
                });

        }

        readonly Font StopFont = new Font("맑은 고딕", 30, FontStyle.Bold);

        public class UIButton
        {
            public RectangleF rect { get; set; }
            public string title { get; set; }
            public string cmd { get; set; }
            public bool Visible { get; set; }
        }
        public List<UIButton> Buttons = new List<UIButton>();
        public delegate void ButtonClickHandler(UIButton idx);
        public event ButtonClickHandler ButtonClick;

        void DrawWarning(Graphics g)
        {

            string warnmsg = string.Empty;
            string butcmd = string.Empty;
            if (dev_agv != null)
            {
                if (dev_agv.error.Emergency)
                    warnmsg = "비상 정지";
                else if (dev_agv.error.line_out_error)
                    warnmsg = "LINE OUT";
                else if (dev_agv.error.Overcurrent)
                    warnmsg = "OVER CURRENT";
                else if (dev_agv.system1.agv_run && dev_agv.system1.stop_by_front_detect)
                    warnmsg = "전방 장애물";
            }
            //if (DesignMode)
            //{
            //    warnmsg = "비.상.정.지";
            //    butcmd = "EMG";
            //}

            if (warnmsg.isEmpty() && stopmessage.isEmpty() == false)
                warnmsg = stopmessage;

            if (warnmsg != "")
            {
                var but = this.Buttons.Where(t => t.title.Equals(warnmsg)).FirstOrDefault();
                if (but == null)
                {
                    but = new UIButton();
                    but.title = warnmsg;
                    this.Buttons.Add(but);
                }
                but.cmd = butcmd;
                var w = this.Width * 0.9f;
                var h = this.Height * 0.4f;
                but.rect = new RectangleF(
                    (float)((this.Width - w) / 2.0f),
                    (float)((this.Height - h) / 2.0f),
                    w, h);
                var rectt = new RectangleF(but.rect.Left, but.rect.Top, but.rect.Width, 10);
                var rectb = new RectangleF(but.rect.Left, but.rect.Bottom - 10, but.rect.Width, 10);
                g.FillRectangle(new SolidBrush(Color.FromArgb(200, Color.White)), but.rect);
                g.FillRectangle(new SolidBrush(Color.FromArgb(220, Color.Red)), rectt);
                g.FillRectangle(new SolidBrush(Color.FromArgb(220, Color.Red)), rectb);

                //var sf = new StringFormat
                //{
                //	LineAlignment = StringAlignment.Center,
                //	Alignment = StringAlignment.Center
                //};
                var sfsize = g.MeasureString(warnmsg, StopFont);
                var scx = (float)((but.rect.Width - sfsize.Width) / 2.0);
                var scy = (float)((but.rect.Height - sfsize.Height) / 2.0);
                g.DrawString(warnmsg, StopFont, Brushes.Black, but.rect.Left + scx + 1, but.rect.Top + scy + 1);
                g.DrawString(warnmsg, StopFont, Brushes.Red, but.rect.Left + scx, but.rect.Top + scy);
                g.DrawRectangle(new Pen(Color.FromArgb(250, Color.Black), 2), but.rect.Left, but.rect.Top, but.rect.Width, but.rect.Height);
            }
            else
            {
                //버튼을 모두 숨긴다.
                foreach (var but in Buttons)
                    but.Visible = false;
            }
        }


        public int frame_direction = 1000 / 10; //초당 4프레임으로 표시한다
        public long frame_direction_ms = 0;
        public int frame_direction_idx = 0;

        void DrawDirection(Graphics g, Rectangle rect, int wheelborder)
        {

            //위쪽에 방향지시등을 그린다.
            var dirterm = 15;
            var ditHeight = 50;
            var dirWidth = (int)(rect.Width / 5.5f);
            var rect_dirup = new Rectangle(
                (int)((rect.Left + rect.Width / 2.0) - (dirWidth / 2.0)),
                rect.Top - ditHeight - dirterm,
                dirWidth,
                (ditHeight - wheelborder));

            var ptsUp = new Point[] {
                new Point( rect_dirup.Left, rect_dirup.Bottom),
                new Point( rect_dirup.Right, rect_dirup.Bottom),
                new Point( (int)(rect_dirup.Left+ rect_dirup.Width/2.0), rect_dirup.Top)
            };

            bool dirup = true;
            if (dev_agv != null) dirup = dev_agv.data.Direction == 'B';

            if (dirup == true)
            {
                g.FillPolygon(Brushes.Lime, ptsUp);
            }
            else g.FillPolygon(new SolidBrush(Color.FromArgb(28, 28, 28)), ptsUp);
            g.DrawPolygon(Pens.Black, ptsUp);



            //아래쪾에 방향지시등을 그린다
            var rect_dirdn = new Rectangle(
                (int)((rect.Left + rect.Width / 2.0) - (dirWidth / 2.0)),
                rect.Bottom + wheelborder + 1 + dirterm,
                dirWidth,
                (ditHeight - wheelborder));

            var ptDn = new Point[] {
                new Point( rect_dirdn.Left, rect_dirdn.Top),
                new Point( rect_dirdn.Right, rect_dirdn.Top),
                new Point( (int)(rect_dirdn.Left+ rect_dirdn.Width/2.0), rect_dirdn.Bottom)
            };

            if (dirup == false)
            {
                g.FillPolygon(Brushes.Lime, ptDn);
            }
            else g.FillPolygon(new SolidBrush(Color.FromArgb(28, 28, 28)), ptDn);
            g.DrawPolygon(Pens.Black, ptDn);



            ////오른쪾에 방향지시등을 그린다
            //var dirR = false;
            //var rect_dirr = new Rectangle(
            //    (int)(rect.Right + dirterm),
            //    (int)(rect.Top + (rect.Height / 2f)),
            //    dirWidth,
            //    (ditHeight - wheelborder));

            //var ptR = new Point[] {
            //    new Point( rect_dirr.Left, rect_dirr.Top),
            //    new Point( rect_dirr.Right, rect_dirr.Top),
            //    new Point( (int)(rect_dirr.Left+ rect_dirr.Width/2.0), rect_dirr.Bottom)
            //};

            //if (dirR == false)
            //{
            //    g.FillPolygon(Brushes.Lime, ptR);
            //}
            //else g.FillPolygon(new SolidBrush(Color.FromArgb(28, 28, 28)), ptR);
            //g.DrawPolygon(Pens.Black, ptR);

        }

        //public bool LimitLU
        //{
        //    get
        //    {
        //        if (dev_plc == null) return true;
        //        return dev_plc.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_LU);
        //    }

        //}
        //public bool LimitLD
        //{
        //    get
        //    {
        //        if (dev_plc == null) return false;
        //        return dev_plc.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_LD);
        //    }
        //}
        //public bool LimitRU
        //{
        //    get
        //    {
        //        if (dev_plc == null) return false;
        //        return dev_plc.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_RU);
        //    }
        //}
        //public bool LimitRD
        //{
        //    get
        //    {
        //        if (dev_plc == null) return true;
        //        return dev_plc.GetValueI(arDev.FakePLC.DIName.PINI_LIMIT_RD);
        //    }
        //}

        void DrawMC(Graphics g)
        {
            var boxw = DisplayRectangle.Width * 0.5f;
            var r = new RectangleF(
                boxw - 80,
                DisplayRectangle.Top + 50,
                boxw,
                DisplayRectangle.Height - 20);
            //g.DrawRectangle(Pens.Red, r.Left, r.Top, r.Width, r.Height);

            var w = r.Width * 0.7f;// this.DisplayRectangle.Width * 0.45;
            var h = r.Height * 0.5f;// this.DisplayRectangle.Height * 0.75;
            var pt = new PointF(r.Left + r.Width / 2.0f, r.Top + r.Height / 2.0f);
            var rect = new RectangleF((float)(pt.X - w / 2.0f), (float)((pt.Y - h / 2.0f) + 20), (float)w, (float)h);

            //3d모형으로 엣지를 넣는다
            // pt = new PointF(DisplayRectangle.Width / 2.1f, DisplayRectangle.Height / 1.5f);
            var sizeX = 150;
            // var sizeY = 100;
            var sizeZ = 150;

            var PtsFront = new PointF[] {
                new PointF(pt.X-sizeX,pt.Y-sizeZ / 2.0f),
                new PointF(pt.X+sizeX,pt.Y-sizeZ / 2.0f),
                new PointF(pt.X+sizeX,pt.Y+sizeZ / 2.0f),
                new PointF(pt.X-sizeX,pt.Y+sizeZ / 2.0f)
            };
            var PtsTop = new PointF[] {
                new PointF(pt.X-sizeX,pt.Y-(sizeZ / 2.0f)),
                new PointF(pt.X+sizeX,pt.Y-(sizeZ / 2.0f)),
                new PointF(pt.X +sizeX + 75,pt.Y- sizeZ),
                new PointF(pt.X - (sizeX / 2.0f)   ,pt.Y-sizeZ)
            };


            var PtsBottom = new PointF[] {
                new PointF(pt.X-sizeX,sizeZ+pt.Y-(sizeZ / 2.0f)),
                new PointF(pt.X+sizeX,sizeZ+pt.Y-(sizeZ / 2.0f)),
                new PointF(pt.X +sizeX +75,sizeZ+pt.Y- sizeZ),
                new PointF(pt.X - (sizeX / 2.0f)   ,sizeZ+pt.Y-sizeZ)
            };

            var PtsBack = new PointF[] {
                 new PointF( (sizeX / 2.0f)+pt.X-sizeX,pt.Y-sizeZ ),
                new PointF( (sizeX / 2.0f)+pt.X+sizeX,pt.Y-sizeZ  ),
                new PointF( (sizeX / 2.0f)+pt.X+sizeX,pt.Y),
                new PointF( (sizeX / 2.0f)+pt.X-sizeX,pt.Y)
            };

            var PtsRight = new PointF[] {
                new PointF( PtsFront[1].X, PtsFront[1].Y ),
                new PointF( PtsBack[1].X, PtsBack[1].Y ),
                new PointF( PtsBack[2].X, PtsBack[2].Y ),
                new PointF( PtsFront[2].X, PtsFront[2].Y )
            };


            var PtsLeft = new PointF[] {
                new PointF( PtsFront[0].X, PtsFront[0].Y ),
                new PointF( PtsBack[0].X, PtsBack[0].Y ),
                new PointF( PtsBack[3].X, PtsBack[3].Y ),
                new PointF( PtsFront[3].X, PtsFront[3].Y )
            };

            //foreach (var p in PtsBottom)
            //{
            //    var xx = p.X - 5;
            //    var yy = p.Y - 5;
            //    var ww = 10;
            //    var hh = 10;
            //    g.DrawEllipse(Pens.Red, xx, yy, ww, hh);
            //}

            //바닥면 출력
            g.FillPolygon(new SolidBrush(Color.FromArgb(150, Color.White)), PtsBottom);
            g.DrawPolygon(Pens.Black, PtsBottom);

            //윗면 출력
            g.FillPolygon(new SolidBrush(Color.FromArgb(50, Color.White)), PtsTop);

            ////뒷면먼저출력
            g.FillPolygon(new SolidBrush(Color.FromArgb(50, Color.White)), PtsBack);

            ////우측출력
            g.FillPolygon(new SolidBrush(Color.FromArgb(10, Color.White)), PtsRight);

            ////좌측출력
            g.FillPolygon(new SolidBrush(Color.FromArgb(10, Color.White)), PtsLeft);

            //안전커버 뒷
            var coverPadding = 10;
            var coverYOffset = -30;
            var coverLYOffset = 0;
            var coverRYOffset = 0;

            //if (LimitRD == true) coverRYOffset = 20;
            //else if (LimitRU == true) coverRYOffset = coverYOffset;

            //if (LimitLD == true) coverLYOffset = 20;
            //else if (LimitLU == true) coverLYOffset = coverYOffset;

            var PtsCoverBack = new PointF[] {
                new PointF( PtsBack[0].X+coverPadding, PtsBack[0].Y+coverLYOffset ),
                new PointF( PtsBack[1].X-coverPadding, PtsBack[1].Y+coverLYOffset ),
                new PointF( PtsBack[2].X-coverPadding, PtsBack[2].Y+coverLYOffset ),
                new PointF( PtsBack[3].X+coverPadding, PtsBack[3].Y+coverLYOffset )
            };

            var PtsCoverFront = new PointF[] {
                new PointF( PtsFront[0].X+coverPadding, PtsFront[0].Y+coverRYOffset ),
                new PointF( PtsFront[1].X-coverPadding, PtsFront[1].Y+coverRYOffset ),
                new PointF( PtsFront[2].X-coverPadding, PtsFront[2].Y+coverRYOffset ),
                new PointF( PtsFront[3].X+coverPadding, PtsFront[3].Y+coverRYOffset )
            };

            //if (LimitLU == true)
            //{
            //    g.FillPolygon(new SolidBrush(Color.FromArgb(100, Color.Red)), PtsCoverBack);
            //    g.DrawPolygon(new Pen(Color.DarkRed, 2), PtsCoverBack);
            //}
            //else if (LimitLD == true)
            //{
            //    g.FillPolygon(new SolidBrush(Color.FromArgb(100, Color.Blue)), PtsCoverBack);
            //    g.DrawPolygon(new Pen(Color.DarkBlue, 2), PtsCoverBack);
            //}
            //else
            {
                g.FillPolygon(new SolidBrush(Color.FromArgb(100, Color.Gray)), PtsCoverBack);
                g.DrawPolygon(Pens.DimGray, PtsCoverBack);
            }

            //g.DrawPolygon(Pens.Orange, PtsCoverBack);

            g.FillPolygon(new SolidBrush(Color.FromArgb(50, Color.White)), PtsFront);
            // g.DrawPolygon(Pens.Black, PtsFront);

            //if (LimitRU == true)
            //{
            //    g.FillPolygon(new SolidBrush(Color.FromArgb(150, Color.Red)), PtsCoverFront);
            //    g.DrawPolygon(new Pen(Color.DarkRed, 2), PtsCoverFront);
            //}
            //else if (LimitRD == true)
            //{
            //    g.FillPolygon(new SolidBrush(Color.FromArgb(150, Color.Blue)), PtsCoverFront);
            //    g.DrawPolygon(new Pen(Color.DarkBlue, 2), PtsCoverFront);
            //}
            //else
            {
                g.FillPolygon(new SolidBrush(Color.FromArgb(150, Color.Gray)), PtsCoverFront);
                g.DrawPolygon(Pens.DimGray, PtsCoverFront);
            }

            //중앙포인트
            g.FillEllipse(Brushes.White, pt.X - 2, pt.Y - 2, 4f, 4f);

            ////button - start
            //var buttonSize = 15;
            //var offset = 10;
            //g.FillEllipse(Brushes.Red, offset * 2.7f + PtsTop[0].X - buttonSize / 2.0f, -offset + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize);
            //g.DrawEllipse(Pens.Black, offset * 2.7f + PtsTop[0].X - buttonSize / 2.0f, -offset + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize);

            //g.FillEllipse(Brushes.Blue, offset * 4.2f + PtsTop[0].X - buttonSize / 2.0f, -offset*2.5f + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize);
            //g.DrawEllipse(Pens.Black, offset * 4.2f + PtsTop[0].X - buttonSize / 2.0f, -offset * 2.5f + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize);

            //g.FillEllipse(Brushes.Green, offset * 5.5f + PtsTop[0].X - buttonSize / 2.0f, -offset * 4.0f + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize);
            //g.DrawEllipse(Pens.Black, offset * 5.5f + PtsTop[0].X - buttonSize / 2.0f, -offset * 4.0f + PtsTop[0].Y - buttonSize / 2.0f, buttonSize, buttonSize);

        }

        //void DrawBattery(Graphics g)
        //{
        //    //우측 끝에 세로로 표시한다
        //    int r = 10;
        //    int w = 25;
        //    int y = 10;
        //    Rectangle rect = new Rectangle(DisplayRectangle.Right - w - r, y, w, DisplayRectangle.Height - (y * 2));
        //    var ph = (this.ChargeLevel / 100.0) * rect.Height;
        //    Rectangle rectp = new Rectangle(rect.Left, (int)(rect.Top + rect.Height - ph), rect.Width, (int)ph);

        //    Color pColor = Color.Gold;
        //    if (ChargeLevel <= 40) pColor = Color.Tomato;
        //    else if (ChargeLevel >= 80) pColor = Color.Lime;


        //    if (rectp.Height > 1)
        //    {
        //        using (LinearGradientBrush b = new LinearGradientBrush(rectp, pColor, Color.FromArgb(150, 150, 150), LinearGradientMode.Vertical))
        //            g.FillRectangle(b, rectp);

        //    }


        //    //for (int i = 1; i < 10; i++)
        //    //{
        //    //    var ly = (int)( rect.Height *  ((i*1.0) / 10.0) );
        //    //    g.DrawLine(Pens.Gray, rect.Left, rect.Top + ly, rect.Right, rect.Top + ly);
        //    //    g.DrawString((10-i).ToString(), this.Font, Brushes.Gray, rect.Left+5, ly+5);
        //    //}


        //    //전체테두리
        //    using (Pen p = new Pen(Color.FromArgb(100, Color.Black)))
        //        g.DrawRectangle(p, rect);


        //}

        public class item
        {

            public bool Enable_Direction { get; set; }
            public Color BackColor1 { get; set; }
            public Color BackColor2 { get; set; }
            public Color ForeColor { get; set; }
            public Color ShadowColor { get; set; }
            public Color BorderColor { get; set; }

            public Color RightColor { get; set; }
            public Color LeftColor { get; set; }

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

            public item()
            {
                BorderColor = Color.FromArgb(100, 100, 100);
                fullrect = Rectangle.Empty;
                leftrect = Rectangle.Empty;
                rightrect = Rectangle.Empty;
                BackColor1 = Color.White;
                BackColor2 = Color.Transparent;
                ForeColor = Color.DimGray;
                ShadowColor = Color.Black;
                Enable_Direction = true;
            }



            public string Title { get; set; }

            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)
                {
                    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));
                }
            }

            if (Buttons.Any())
            {
                //마우스위치가 아이템에 포함되어있다면
                var focusItem = Buttons.Where(t => t.rect.Contains(e.Location)).FirstOrDefault();
                if (focusItem != null)
                {
                    //ItemClick?.Invoke(this, new ItemClickEventArgs(focusItem));
                    ButtonClick?.Invoke(focusItem);
                }
            }
            Invalidate();
        }



    }
}
