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 Project
{
    public partial class fModelM : Form
    {
        short axisIndex = 0;
        eAxis axis = eAxis.X_PICKER;//

        public string Value = string.Empty;
        // Dialog.fBlurPanel fb;

        public fModelM()
        {
            InitializeComponent();

            if (System.Diagnostics.Debugger.IsAttached == false)
            {
                // fb = new Dialog.fBlurPanel();
                //fb.Show();
            }

            
            this.KeyPreview = true;
            this.KeyDown += (s1, e1) => { if (e1.KeyCode == Keys.Escape) this.Close(); };
            this.StartPosition = FormStartPosition.CenterScreen;
            this.FormClosed += __Closed;

            this.lbTitle.MouseMove += LbTitle_MouseMove;
            this.lbTitle.MouseUp += LbTitle_MouseUp;
            this.lbTitle.MouseDown += LbTitle_MouseDown;

            var axlist = Enum.GetNames(typeof(eAxis));
            var axvalues = Enum.GetValues(typeof(eAxis));

            var preValueList = new List<ushort>();
            preValueList.AddRange(new ushort[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 });

            for (int i = 0; i < axlist.Length; i++)
            {
                var axTitle = axlist[i];
                var axradio = new RadioButton();
                axradio.Tag = i; //축번호
                axradio.Text = string.Format("[{0}] {1}", i, axTitle);
                axradio.Click += radClick_MotAxisSelect;    //클릭작업
                axradio.AutoSize = true;
                this.flowLayoutPanel1.Controls.Add(axradio);
                preValueList.AddRange(new ushort[] { 0, 1, 1, 1, 1, 1, 1, 1, 1 });

                //   this.tabControl1.TabPages[i].Text = string.Format("Axis [{0}]", i); //탭페이지 이름 변경
                tblFG.setTitle(i + 1, 0, axTitle); //모니터링 축정보의 이름 지정
            }

            tblFG.MatrixSize = new Point(tblFG.MatrixSize.X, axlist.Length + 1);
            tblFG.Values = preValueList.ToArray();
            for (int i = 1; i <= 6; i++)
                tblFG.setItemTextAlign(i, 0, ContentAlignment.MiddleLeft);

            //링크레이블과 버튼 연결
            AttachEvents();



        }
        private void __Load(object sender, EventArgs e)
        {
            this.Show();
            ////'Application.DoEvents();

            this.ds1.Clear();
            this.ds1.MCModel.Merge(Pub.mdm.dataSet.MCModel);
            this.ds1.MCModel.AcceptChanges();
            this.ds1.MCModel.TableNewRow += Model_TableNewRow;

            this.bs.Filter = "isnull(title,'') <> ''";
            this.bsPosData.Filter = "isnull(title,'') = '' and isnull(motindex,-1) = -1";
            this.tmDisplay.Start();

            //dispal current
            if (Pub.Result.isSetmModel)
            {
                arLabel18.Text = Pub.Result.mModel.Title;
                //find data
                var datas = this.ds1.MCModel.Select("", this.bs.Sort);
                for (int i = 0; i < datas.Length; i++)
                {
                    if (datas[i]["Title"].ToString() == Pub.Result.mModel.Title)
                    {
                        this.bs.Position = i;
                        break;
                    }
                }
            }
            else arLabel18.Text = "--";

            if (this.ds1.MCModel.Rows.Count < 1)
            {
                var newdr = this.ds1.MCModel.NewMCModelRow();
                newdr.Title = "Default";
                newdr.pidx = -1;
                newdr.PosIndex = -1;
                newdr.idx = ds1.MCModel.Rows.Count + 1;
                this.ds1.MCModel.AddMCModelRow(newdr);
            }

            //this.axisIndex = 0; //기본Z축
            radClick_MotAxisSelect(this.flowLayoutPanel1.Controls[0], null);
            var rad = flowLayoutPanel1.Controls[0] as RadioButton;
            rad.Checked = true;

            var fctl = new Dialog.QuickControl();
            fctl.TopLevel = false;
            fctl.Visible = true;
            fctl.Padding = new Padding(0, 0, 0, 0);
            fctl.ForeColor = Color.Black;
            fctl.panBG.BackColor = Color.White;
            fctl.panBG.ForeColor = Color.Black;
            
            fctl.groupBox1.ForeColor = Color.Black;
			//fctl.groupBox2.ForeColor = Color.Black;
			fctl.groupBox3.ForeColor = Color.Black;

			this.tabPage2.Controls.Add(fctl);
            fctl.Dock = DockStyle.Fill;
            fctl.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            //fctl.FormBorderStyle =.Visible = false;
            //fctl.panTopMenuDiv.Visible = false;
            ///      fctl.panBG.BackColor = this.panel6.BackColor;
            fctl.panBG.BorderStyle = BorderStyle.None;
            fctl.Show();
            fctl.Dock = DockStyle.Fill;
            Pub.log.RaiseMsg += log_RaiseMsg;
            //Pub.flag.set(eFlag.JOG, true, "MOTION CONTROL");
        }


        void AttachEvents()
        {
            var EventConnectControls = new List<Control>();
            EventConnectControls.Add(groupBox4);
            // foreach (TabPage page in this.tabControl1.TabPages)
            //        EventConnectControls.Add(page);

            //linklabel 과 button 에 클릭 이벤트 생성
            foreach (Control page in EventConnectControls)
            {
                foreach (var ctl in page.Controls)
                {
                    if (ctl.GetType() == typeof(arFrame.Control.MotLinkLabel))
                    {
                        var label = ctl as arFrame.Control.MotLinkLabel;
                        if (label.motValueControl != null) label.LinkClicked += label_LinkClicked;

                    }
                    else if (ctl.GetType() == typeof(arFrame.Control.MotCommandButton))
                    {
                        var button = ctl as arFrame.Control.MotCommandButton;
                        if (button.motValueControl != null) button.Click += button_Click;
                    }
                }
            }
        }

        void button_Click(object sender, EventArgs e)
        {
            var ctl = sender as arFrame.Control.MotCommandButton;
            var nud = ctl.motValueControl as arFrame.Control.MotValueNumericUpDown;
            var nudAcc = ctl.motAccControl;// as arFrame.Control.MotValueNumericUpDown;
            var nudSpd = ctl.motSpdControl;
            if (nud.MotionIndex < 0)
            {
                Util.MsgE("모션 축 번호가 지정되지 않았습니다\n\n" +
                    "이름 : " + ctl.Name + "\n" +
                    "제목 : " + ctl.Text);
                return;
            }
            if ((nudAcc == null || nudSpd == null) && ctl.motCommand != arFrame.Control.MotCommandButton.eCommand.AcceptPosition)
            {
                Util.MsgE("속도/가속도 컨트롤이 지정되지 않았습니다\n\n" +
                    "이름 : " + ctl.Name + "\n" +
                    "제목 : " + ctl.Text);
                return;
            }

            var axis = (eAxis)nud.MotionIndex;
            var pos = (double)nud.Value;

            //모션이 초기화가 안되있다면 오류로 처리한다
            if (Pub.mot.isHomeSet[nud.MotionIndex] == false)
            {
                Util.MsgE("해당 축은 홈 검색이 완료되지 않았습니다.\n먼저 홈 검색을 완료 하세요");
                return;
            }



            switch (ctl.motCommand)
            {
                case arFrame.Control.MotCommandButton.eCommand.AcceptPosition:

                    var msg1 = string.Format("모션의 설정값을 변경 하시겠습니까\n" +
                       "축 : {0}\n" +
                       "변경전 : {1}\n" +
                       "변경후 : {2}\n" +
                       "변경 후 '저장'을 눌러야 영구 기록 됩니다", axis, Pub.mot.dACTPOS[nud.MotionIndex], pos, nud.Value);

                    if (Util.MsgQ(msg1) != System.Windows.Forms.DialogResult.Yes) return;

                    ChangeCurrentPosition(nud.MotionIndex, nud);
                    break;
                case arFrame.Control.MotCommandButton.eCommand.AbsoluteMove:
                case arFrame.Control.MotCommandButton.eCommand.RelativeMove:

                    var speed = (double)nudSpd.Value;
                    var acc = (double)nudAcc.Value;




                    var relative = false;
                    if (ctl.motCommand == arFrame.Control.MotCommandButton.eCommand.RelativeMove)
                        relative = true;

                    var msg = string.Format("모션의 위치를 변경 하시겠습니까\n" +
                        "축 : {0}\n" +
                        "현재위치 : {1}\n" +
                        "대상위치 : {2}\n" +
                        "이동 시 충돌 가능성이 있는지 반드시 확인 하세요", axis, Pub.mot.dACTPOS[nud.MotionIndex], pos);

                    if (Util.MsgQ(msg) != System.Windows.Forms.DialogResult.Yes) return;

                    if (!Util_Mot.Move(axis, pos, speed, acc, relative))
                        Pub.log.AddE("MOT:MOVE_:" + axis.ToString() + ",Msg=" + Pub.mot.errorMessage);
                    break;
            }
        }

        void label_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            var ctl = sender as arFrame.Control.MotLinkLabel;
            Pub.ChangeUIPopup(ctl.motValueControl);
        }

        private void __Closed(object sender, FormClosedEventArgs e)
        {
            //if (fb != null) fb.Dispose();
            this.tmDisplay.Enabled = false;
            this.ds1.MCModel.TableNewRow -= Model_TableNewRow;
            //Pub.flag.set(eFlag.JOG, false, "MOTION CONTROL");
        }


        #region "Mouse Form Move"

        private Boolean fMove = false;
        private Point MDownPos;

        private void LbTitle_DoubleClick(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Maximized) this.WindowState = FormWindowState.Normal;
            else this.WindowState = FormWindowState.Maximized;
        }
        private void LbTitle_MouseMove(object sender, MouseEventArgs e)
        {
            if (fMove)
            {
                Point offset = new Point(e.X - MDownPos.X, e.Y - MDownPos.Y);
                this.Left += offset.X;
                this.Top += offset.Y;
                offset = new Point(0, 0);
            }
        }
        private void LbTitle_MouseUp(object sender, MouseEventArgs e)
        {
            fMove = false;
        }
        private void LbTitle_MouseDown(object sender, MouseEventArgs e)
        {
            MDownPos = new Point(e.X, e.Y);
            fMove = true;
        }

        #endregion


        void log_RaiseMsg(DateTime LogTime, string TypeStr, string Message)
        {
            if (Message.StartsWith("[EO]") || Message.StartsWith("EO"))
            {
                return;
            }
            this.logTextBox1.AddMsg(LogTime, TypeStr, Message);
        }



        Color sbBackColor = Color.FromArgb(200, 200, 200);


        void Model_TableNewRow(object sender, DataTableNewRowEventArgs e)
        {
            // e.Row["SlotCount"] = 20;
        }

        private void modelBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {

        }

        private void bs_CurrentChanged(object sender, EventArgs e)
        {
            //z range 을 표시한다.

            //z position 영역을 문자로 변환한다.
            //this.list
            var drv = this.bs.Current as DataRowView;
            if (drv == null) return;
            var dr = drv.Row as DataSet1.MCModelRow;
        }

        private void tmDisplay_Tick(object sender, EventArgs e)
        {
            button7.BackColor = Util_DO.GetIOInput(eDIName.PICKER_SAFE) ? Color.Lime : Color.DimGray; //*210111

            if (Pub.joystick.IsOpen)
                this.lbTitle.Text = "MODEL(MOTION) SETTING - JOYSTICK GROUP:" + Pub.Result.JoystickAxisGroup.ToString();
            else
                this.lbTitle.Text = "MODEL(MOTION) SETTING";

            if (Pub.mot.IsInit == false)
            {
                if (groupBox3.Enabled == true) groupBox3.Enabled = false;
            }
            else
            {
                if (groupBox3.Enabled == false) groupBox3.Enabled = true;

                //각축별 기본 상태를 표시해준다.
                for (int axis = 0; axis < Pub.system.MotaxisCount; axis++)
                {
                    this.tblFG.setValue(axis + 1, 0, Pub.mot.isSERVOON[axis] ? "title" : "orange");
                    this.tblFG.setTitle(axis + 1, 1, string.Format("{0}mm", Pub.mot.dCMDPOS[axis]));
                    this.tblFG.setTitle(axis + 1, 2, string.Format("{0}mm", Pub.mot.dACTPOS[axis]));
                    this.tblFG.setValue(axis + 1, 3, Pub.mot.isOrg[axis] ? "blue" : "gray");  //MotStatus_Home[axis].BackColor = Pub.mot.isOrg[axis] ? Color.Lime : sbBackColor;
                    this.tblFG.setValue(axis + 1, 4, Pub.mot.isLimitN[axis] ? "red" : "gray");  //MotStatus_NLIM[axis].BackColor = Pub.mot.isLimitN[axis] ? Color.Red : sbBackColor;
                    this.tblFG.setValue(axis + 1, 5, Pub.mot.isLimitP[axis] ? "red" : "gray");  //MotStatus_PLIM[axis].BackColor = Pub.mot.isLimitP[axis] ? Color.Red : sbBackColor;
                    this.tblFG.setValue(axis + 1, 6, Pub.mot.isINP[axis] ? "blue" : "gray");  //MotStatus_INP[axis].BackColor = Pub.mot.isINP[axis] ? Color.Lime : sbBackColor;
                    this.tblFG.setValue(axis + 1, 7, Pub.mot.isSERVOAlarm[axis] ? "red" : "gray");  //MotStatus_ALM[axis].BackColor = Pub.mot.isSERVOAlarm[axis] ? Color.Lime : sbBackColor;
                    this.tblFG.setValue(axis + 1, 8, Pub.mot.isHomeSet[axis] ? "green" : "gray");  //MotStatus_SVON[axis].BackColor = Pub.mot.isHomeSet[axis] ? Color.Lime : Color.Magenta;
                }
            }
            this.tblFG.Invalidate();
        }

        private void dv_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {

        }

        private void btSelect_Click(object sender, EventArgs e)
        {

        }


        #region "jog function"

        private void button1_Click(object sender, EventArgs e)
        {
            //절대값 이동
            var pos = (double)nudPosAbs.Value;
            var vel = (double)nudJogVel.Value;
            Util_Mot.Move(this.axis, pos, vel, 500, false, !chkJogMoveForce.Checked,!chkJogMoveForce.Checked);
            Pub.log.AddI(string.Format("{0}번 축 수동이동(ABS) {1}mm", axisIndex, pos));
        }

        private void button3_Click_1(object sender, EventArgs e)
        {

            //상대값 이동
            var pos = (double)nudPosRel.Value;
            var vel = (double)nudJogVel.Value;
            Util_Mot.Move(this.axis, pos, vel, 500, true, !chkJogMoveForce.Checked, !chkJogMoveForce.Checked);
            Pub.log.AddI(string.Format("{0}번 축 수동이동(REL) {1}mm", axisIndex, pos));
        }


        private void btJogHome_Click(object sender, EventArgs e)
        {
            //jog-home

            var dlg = Util.MsgQ(string.Format("{0} 축의 홈 검색을 실행하시겠습니까?", this.axis));
            if (dlg != System.Windows.Forms.DialogResult.Yes) return;
            var rlt = Util_Mot.Home("Model(UserControl)", this.axis);
            if (rlt == false)
            {
                Util.MsgE(Pub.mot.errorMessage);
                return;
            }
            Pub.log.Add(string.Format("user click : home ({0})", axisIndex));
        }

        private void btJogPClear_Click(object sender, EventArgs e)
        {
            var dlg = Util.MsgQ("위치값을 초기화 하시겠습니까?\n" +
                "실 사용전에는 반드시 홈 작업을 진행하세요");
            if (dlg != System.Windows.Forms.DialogResult.Yes) return;
            //jog pos-clear            
            Pub.mot.ClearPosition((short)axisIndex);
            Pub.mot.isHomeSet[axisIndex] = false; //홈셋도 풀어야한다  201222
            Pub.log.Add(string.Format("user click : pos clear ({0})", axisIndex));
        }

        private void btJogAClear_Click(object sender, EventArgs e)
        {
            //jog-alaram clear
            Pub.mot.SetAlarmClearOn(this.axisIndex);
            System.Threading.Thread.Sleep(200);
            Pub.mot.SetAlarmClearOff(this.axisIndex);
            Pub.log.Add(string.Format("user click : alarm clear ({0})", axisIndex));
        }

        private void btJogBrake_Click(object sender, EventArgs e)
        {
            //jog-brake
            //var curstate = Util_DO.GetIOOutput(eDOName.BRAKE_OFF);
            //Util_DO.SetBrake(!curstate);
            //Pub.log.Add(string.Format("user click : set brake ({0})", axisIndex));
        }

        private void btJogSVon_Click(object sender, EventArgs e)
        {
            //jog-svon
            var curstate = Pub.mot.isSERVOON[axisIndex];
            Pub.mot.SetSVON((short)axisIndex, !curstate);
            Pub.log.Add(string.Format("user click : servo on ({0})", axisIndex));
        }


        private void btJogStop_Click(object sender, EventArgs e)
        {
            //jog-stop
            Pub.mot.MoveStop("JOG", this.axisIndex);
            Pub.log.Add(string.Format("user click : move stop ({0})", axisIndex));
        }

        private void btJogDown_Click(object sender, MouseEventArgs e)
        {
            //jog-moouse down
            var bt = sender as Button;
            var tag = bt.Tag.ToString();
            var vel1 = (double)this.nudJogVel.Value;
            var acc1 = (double)1000.0;

            arDev.AzinAxt.eMotionDirection motDir = arDev.AzinAxt.eMotionDirection.Positive;
            if (tag == "CCW") motDir = arDev.AzinAxt.eMotionDirection.Negative;

            Boolean jogMoveForce = this.chkJogMoveForce.Checked;
            if (!Pub.mot.JOG(this.axisIndex, motDir, vel1, acc1, acc1, false, !jogMoveForce))
                Pub.log.AddE("MOT:JOG:" + tag + ":" + Pub.mot.errorMessage);

            Pub.log.Add(string.Format("user click : jog start ({0}) - {1}", axisIndex, tag));
        }

        private void btJogUp_Click(object sender, MouseEventArgs e)
        {
            //jog-mouseup
            var bt = sender as Button;
            var tag = bt.Tag.ToString();
            Pub.mot.MoveStop("JOG", this.axisIndex);   //선택된 축을 멈춘다.
            Pub.log.Add(string.Format("user click : jog stop ({0})", axisIndex));
        }

        #endregion

        //void ChangeUIPopup(NumericUpDown valueCtl)
        //{
        //    var value = valueCtl.Value.ToString();
        //    Dialog.fInput f = new Dialog.fInput(value);
        //    if (f.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        //        valueCtl.Value = decimal.Parse(f.tbInput.Text);
        //}
        void ChangeCurrentPosition(int Axis, NumericUpDown valueCtl)
        {
            valueCtl.Value = (decimal)Pub.mot.dACTPOS[Axis];
        }

        private void toolStripButton2_Click_1(object sender, EventArgs e)
        {
            //iocontrol
            var f = new Dialog.QuickControl();
            f.TopMost = true;
            f.Opacity = 0.95;
            f.Show();
        }

        private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
        {

        }

        private void radClick_MotAxisSelect(object sender, EventArgs e)
        {
            var rad = sender as RadioButton;
            this.axisIndex = short.Parse(rad.Tag.ToString());
            this.axis = (eAxis)this.axisIndex;
            var axisTitle = rad.Text.Substring(3).Trim(); //.Substring(rad.Text.Substring(3));

            var drv = this.bs.Current as DataRowView;
            if (drv == null) return;

            var dr = drv.Row as DataSet1.MCModelRow;

            //모든 라디오 박스의 색상을 원복한다
            foreach (RadioButton rd in this.flowLayoutPanel1.Controls) rd.ForeColor = Color.White;
            rad.ForeColor = Color.Yellow; //선택된 것은 라임색으로 변경

            //          this.tabControl1.SelectedIndex = axisIndex; //탭메뉴를 변경해준다.

            //선택된 축에따라서 조그모드 성격을 변경한다
            if (axisTitle.StartsWith("Z_"))
            {
                //           nudJogVel.Value = this.nudSpdLoaderSlow.Value;
                btJogLeft.Visible = false;
                btJogRight.Visible = false;
                btJogUp.Text = "UP(-)"; btJogUp.Visible = true; btJogUp.Tag = "CCW";
                btJogDn.Text = "DOWN(+)"; btJogDn.Visible = true; btJogDn.Tag = "CW";
            }
            else if (axisTitle.StartsWith("X_"))
            {
                //         nudJogVel.Value = nudSpdIndex1Slow.Value;
                btJogUp.Visible = false;
                btJogDn.Visible = false;
                btJogLeft.Text = "LEFT(-)"; btJogLeft.Visible = true; btJogLeft.Tag = "CCW";
                btJogRight.Text = "RIGHT(+)"; btJogRight.Visible = true; btJogRight.Tag = "CW";
            }
            else if (axisTitle.StartsWith("Y_"))
            {
                //     nudJogVel.Value = nudSpdVision.Value;
                btJogLeft.Visible = false;
                btJogRight.Visible = false;
                btJogUp.Text = "FAR(+)"; btJogUp.Visible = true; btJogUp.Tag = "CW";
                btJogDn.Text = "NEAR(-)"; btJogDn.Visible = true; btJogDn.Tag = "CCW";
            }
            RefreshMotorPosition();
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {

        }

        private void tbClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void bs_CurrentChanged_1(object sender, EventArgs e)
        {

            //BindingData();
        }
        void RefreshMotorPosition()
        {
            var drv = this.bs.Current as DataRowView;
            if (drv == null)
            {
                bsPosData.Filter = string.Format("pidx={0}", -1);   //아무것도 보이지 않게 한다
            }
            else
            {
                //해당 선택된 모터의 값을 체크한다
                var dr = drv.Row as DataSet1.MCModelRow;

                //위치정보 표시
                bsPosData.Filter = string.Format("pidx={0} and motindex = {1}", dr.idx, this.axisIndex);

                //(위치정보) 데이터수량이 맞지 않으면 재 생성한다
                string[] list = null;
                Array val = null;
                Type axType = null;
                if (this.axisIndex == (int)eAxis.X_PICKER) axType = typeof(eAxisPXPos);
                else if (this.axisIndex == (int)eAxis.Z_PICKER) axType = typeof(eAxisPZPos);
                else if (this.axisIndex == (int)eAxis.Z_THETA) axType = typeof(eAxisPTPos);

                else if (this.axisIndex == (int)eAxis.PL_MOVE) axType = typeof(eAxisPLMovePos);
                else if (this.axisIndex == (int)eAxis.PL_UPDN) axType = typeof(eAxisPLUPDNPos);
                else if (this.axisIndex == (int)eAxis.PR_MOVE) axType = typeof(eAxisPRMovePos);
                else if (this.axisIndex == (int)eAxis.PR_UPDN) axType = typeof(eAxisPRUPDNPos);


                list = Enum.GetNames(axType);
                val = Enum.GetValues(axType);

                var sb = new System.Text.StringBuilder();
                var cntI = 0;
                var cntE = 0;
                var cntD = 0;

                //posidx == -1인 데이터는 모두 소거한다
                var dellist = ds1.MCModel.Where(t => t.pidx == dr.idx && t.MotIndex == this.axisIndex && t.PosIndex == -1).ToList();    //메인목록은 남겨둔다
                cntD += dellist.Count();
                foreach (var item in dellist)
                    item.Delete();
                ds1.MCModel.AcceptChanges();

                //모든데이터의 체크상태를 off한다.
                var alllist = this.ds1.MCModel.Where(t => t.pidx == dr.idx && t.MotIndex == this.axisIndex);
                foreach (var item in alllist)
                    item.Check = false;
                ds1.MCModel.AcceptChanges();

                for (int i = 0; i < list.Length; i++)
                {
                    var arrTitle = list[i];
                    var arrIndex = (short)((eAxis)(val.GetValue(i)));

                    //이 값이 데이터가 없다면 추가하고, 있다면 이름을 검사해서 결과를 안내한다
                    var pDr = this.ds1.MCModel.Where(t => t.pidx == dr.idx && t.PosIndex == arrIndex && t.MotIndex == axisIndex).FirstOrDefault();
                    if (pDr == null)
                    {
                        cntI += 1;
                        var newdr = this.ds1.MCModel.NewMCModelRow();

                        if (ds1.MCModel.Rows.Count == 0) newdr.idx = 1;
                        else newdr.idx = ds1.MCModel.Max(t => t.idx) + 1;

                        newdr.pidx = dr.idx;
                        newdr.MotIndex = this.axisIndex;
                        newdr.PosIndex = arrIndex;
                        newdr.PosTitle = arrTitle;
                        newdr.Position = 0.0;
                        newdr.Speed = 50;
                        newdr.SpeedAcc = 100;
                        newdr.Check = true;

                        this.ds1.MCModel.AddMCModelRow(newdr);
                        newdr.EndEdit();
                        sb.AppendLine("항목 추가 : " + arrTitle);
                    }
                    else
                    {
                        //이름이 다르다면 추가해준다.
                        if (pDr.PosTitle != arrTitle)
                        {
                            sb.AppendLine("(위치)항목 변경 : " + pDr.PosTitle + " => " + arrTitle);
                            cntE += 1;
                            pDr.PosTitle = arrTitle;
                            pDr.EndEdit();
                        }
                        pDr.Check = true;
                    }
                }

                //미사용개체 삭제한다

                var NotUseList = this.ds1.MCModel.Where(t => t.pidx == dr.idx && t.MotIndex == this.axisIndex && t.Check == false).ToList();
                cntD += NotUseList.Count();
                foreach (var item in NotUseList)
                    item.Delete();
                ds1.MCModel.AcceptChanges();

                if (cntI > 0) sb.AppendLine("추가수량 : " + cntI.ToString());
                if (cntE > 0) sb.AppendLine("변경수량 : " + cntE.ToString());
                if (cntD > 0) sb.AppendLine("삭제수량 : " + cntD.ToString());

                //최종 확정
                this.ds1.MCModel.AcceptChanges();

                if (sb.Length > 0)
                {
                    Util.MsgI(sb.ToString());
                }
            }
        }

        private void chkJogMoveForce_Click(object sender, EventArgs e)
        {
            if (chkJogMoveForce.Checked)
            {
                Util.MsgI(
                    "조그 강제 이동시에는 충돌 조건을 검사하지 않습니다\n" +
                    "셔틀 이동 시 주변 장애물을 반드시 확인하시기 바랍니다\n" +
                    "'강제이동' 은 티칭작업시에만 사용하세요");
            }
        }

        private void button10_Click(object sender, EventArgs e)
        {

        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {


        }

        private void button31_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
        {

        }

        private void btCapture_Click(object sender, EventArgs e)
        {

        }

        private void btAdd_Click(object sender, EventArgs e)
        {
            var newdr = this.ds1.MCModel.NewMCModelRow();// this.bs.AddNew() as DataRowView;
            newdr["Title"] = DateTime.Now.ToShortDateString();
            newdr["pidx"] = -1;
            newdr.PosIndex = -1;
            newdr["idx"] = this.ds1.MCModel.Rows.Count + 1;
            this.ds1.MCModel.AddMCModelRow(newdr);
            this.bs.Position = this.bs.Count - 1;

            //모터축을 자동 선택해줌
            radClick_MotAxisSelect(this.flowLayoutPanel1.Controls[0], null);
        }

        private void btDel_Click(object sender, EventArgs e)
        {
            var drv = this.bs.Current as DataRowView;
            if (drv == null) return;
            var dlg = Util.MsgQ("현재 선택된 자료를 삭제하시겠습니까?");
            if (dlg != System.Windows.Forms.DialogResult.Yes) return;
            bs.RemoveCurrent();
            this.ds1.MCModel.AcceptChanges();
        }

        private void btSave_Click(object sender, EventArgs e)
        {
            //button - save
            this.dv.Focus();
            this.Validate();
            this.bs.EndEdit();
            this.bsPosData.EndEdit();
            this.Validate();

            //numeric number validation (마지막 아이템이 저장안되는 현상이 있었음)
            //var EventConnectControls = new List<Control>();
            //EventConnectControls.Add(groupBox4);
            ////foreach (TabPage page in this.tabControl1.TabPages)
            ////    EventConnectControls.Add(page);

            ////linklabel 과 button 에 클릭 이벤트 생성
            //foreach (Control page in EventConnectControls)
            //{
            //    //var ctl = page as ContainerControl;
            //    // ctl.Validate();
            //    foreach (var ctl in page.Controls)
            //    {
            //        if (ctl.GetType() == typeof(arFrame.Control.MotLinkLabel))
            //        {
            //            var label = ctl as arFrame.Control.MotLinkLabel;// arFrame.Control.MotLinkLabel;
            //                                                            // label.Validate();

            //        }
            //        else if (ctl.GetType() == typeof(LinkLabel))
            //        {
            //            var link = ctl as LinkLabel;//LinkLabel;
            //            //link.Validate();
            //        }
            //    }
            //}


            //z position 영역을 문자로 변환한다.
            //var drv = this.bs.Current as DataRowView;
            //if (drv == null) return;
            //var dr = drv.Row as DataSet1.MCModelRow;
            //dr.EndEdit();
            //this.ds1.AcceptChanges();

            Dialog.fPassword f = new Dialog.fPassword();
            if (f.ShowDialog() != DialogResult.OK) return;
            if (f.tbInput.Text != Pub.setting.Password_Setup)
            {
                Util.MsgE("Password incorrect");
                return;
            }

            Pub.mdm.dataSet.MCModel.Clear();
            Pub.mdm.dataSet.MCModel.Merge(this.ds1.MCModel);
            Pub.mdm.dataSet.AcceptChanges();
            Pub.mdm.SaveModelM();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //select
            this.Invalidate();
            this.bs.EndEdit();
            var drv = this.bs.Current as DataRowView;
            if (drv == null) return;
            var dr = drv.Row as DataSet1.MCModelRow;
            if (dr.Title == "") return;
            this.Value = dr.Title;
            DialogResult = System.Windows.Forms.DialogResult.OK;
        }

        private void button6_Click(object sender, EventArgs e)
        {
            //적용

            this.bs.EndEdit();
            this.bsPosData.EndEdit();
            this.Validate();

            var drv = this.bs.Current as DataRowView;
            if (drv == null) return;
            var dr = drv.Row as DataSet1.MCModelRow;

            this.Value = dr.Title;

            Pub.Result.mModel.ReadValue(dr.Title, this.ds1.MCModel);
            if (Pub.Result.mModel.isSet)
            {
                Pub.log.AddAT("모션모델선택완료 : " + Pub.Result.mModel.Title);
            }
            else Util.MsgE("적용 실패\n\n대상 모델 명이 없습니다");
        }

        private void button4_Click(object sender, EventArgs e)
        {
            var drv = this.bs.Current as DataRowView;
            if (drv == null) return;
            var dr = drv.Row as DataSet1.MCModelRow;
            var dlg = Util.MsgQ(string.Format("다음 모델 정보를 복사하시겠습니까?\n\n모델명 : {0}", dr.Title));
            if (dlg != System.Windows.Forms.DialogResult.Yes) return;

            var newdr = this.ds1.MCModel.NewMCModelRow();
            Util.CopyData(dr, newdr);
            newdr.Title += "-copy-";
            newdr.idx = this.ds1.MCModel.OrderByDescending(t => t.idx).FirstOrDefault().idx + 1;
            newdr.EndEdit();
            this.ds1.MCModel.AddMCModelRow(newdr);
            if (this.bs.Count > 0) this.bs.Position = this.bs.Count - 1;
        }

        private void arDatagridView2_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            //position click
            var dv = sender as DataGridView;
            var col = this.dvPosition.Columns[e.ColumnIndex];
            var colName = col.Name.ToLower();
            if (colName == "btgo")
            {
                //현재값으로 모터를 이동
                //현재위치값으로 설정
                var cell = dv.Rows[e.RowIndex].Cells["btpos"];
                var value = (double)cell.Value;
                var drv = this.bsPosData.Current as DataRowView;
                var drParent = drv.Row as DataSet1.MCModelRow;

                //일반 속도값을 찾는다
                //var speedDr = drParent.Speed;//  this.ds1.MCModel.Where(t => t.pidx == drParent.idx && t.MotIndex == axisIndex && t.PosIndex == -1 && t.SpdIndex == (int)eAxisSpeed.Normal).FirstOrDefault();
                var speed = drParent.Speed;// speedDr.Speed;// (double)this.nudJogVel.Value;
                var acc = drParent.SpeedAcc;// speedDr.SpeedAcc;// ;  (double)nudAcc.Value;


                var relative = false;
                //if (ctl.motCommand == arFrame.Control.MotCommandButton.eCommand.RelativeMove)
                //    relative = true;

                var msg = string.Format("모션의 위치를 변경 하시겠습니까\n" +
                    "축 : {0}\n" +
                    "현재위치 : {1}\n" +
                    "대상위치 : {2}\n" +
                    "이동속도 : {3}(가속도:{4})\n" +
                    "이동 시 충돌 가능성이 있는지 반드시 확인 하세요", axis, Pub.mot.dACTPOS[axisIndex], value, speed, acc);

                if (Util.MsgQ(msg) != System.Windows.Forms.DialogResult.Yes) return;

                if (!Util_Mot.Move(axis, value, speed, acc, relative, !chkJogMoveForce.Checked, !chkJogMoveForce.Checked))
                    Pub.log.AddE("MOT:MOVE_:" + axis.ToString() + ",Msg=" + Pub.mot.errorMessage);



            }
            else if (colName == "btset")
            {
                //현재위치값으로 설정
                var cell = dv.Rows[e.RowIndex].Cells["btpos"];
                var value = (double)cell.Value;
                var nValue = Pub.mot.dACTPOS[this.axisIndex];


                var msg1 = string.Format("모션의 설정값을 변경 하시겠습니까\n" +
                       "축 : {0}\n" +
                       "변경전 : {1}\n" +
                       "변경후 : {2}\n" +
                       "변경 후 '저장'을 눌러야 영구 기록 됩니다", this.axis, value, nValue);

                if (Util.MsgQ(msg1) != System.Windows.Forms.DialogResult.Yes) return;
                cell.Value = nValue;
            }
            else if (colName == "btpos")
            {
                //현재값 변경 팝업
                var cell = dv.Rows[e.RowIndex].Cells[e.ColumnIndex];
                var value = (double)cell.Value;
                value = Pub.ChangeValuePopup(value, "위치 입력");
                cell.Value = value;
            }
            else if (colName == "btspeed")
            {
                //현재값 변경 팝업
                var cell = dv.Rows[e.RowIndex].Cells[e.ColumnIndex];
                var value = (double)cell.Value;
                value = Pub.ChangeValuePopup(value, "속도 입력");
                cell.Value = value;
            }
            else if (colName == "btacc")
            {
                //현재값 변경 팝업
                var cell = dv.Rows[e.RowIndex].Cells[e.ColumnIndex];
                var value = (double)cell.Value;
                value = Pub.ChangeValuePopup(value, "가속도 입력");
                cell.Value = value;
            }
            else if (colName == "btdcc")
            {
                //현재값 변경 팝업
                var cell = dv.Rows[e.RowIndex].Cells[e.ColumnIndex];
                if (cell.Value.ToString().isEmpty()) cell.Value = "0";
                var value = (double)cell.Value;
                value = Pub.ChangeValuePopup(value, "감속도 입력");
                cell.Value = value;
            }

        }


        private void lbTitle_Click(object sender, EventArgs e)
        {

        }

        private void lbTitle_DoubleClick_1(object sender, EventArgs e)
        {
            //if (fb != null) fb.Hide();
        }

        private void linkLabel8_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            //jopgspeed
            var value = (double)nudJogVel.Value;
            value = Pub.ChangeValuePopup(value, "속도 입력");
            nudJogVel.Value = (decimal)value;
        }

        private void linkLabel10_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            //absvalue
            var value = (double)this.nudPosAbs.Value;
            value = Pub.ChangeValuePopup(value, "속도 입력");
            nudPosAbs.Value = (decimal)value;
        }

        private void linkLabel11_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            //reelvalu
            var value = (double)nudPosRel.Value;
            value = Pub.ChangeValuePopup(value, "속도 입력");
            nudPosRel.Value = (decimal)value;
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            var dlg = Util.MsgQ("모든 이동좌표의 속도를 일괄 변경하시겠습니까?");
            if (dlg != System.Windows.Forms.DialogResult.Yes) return;
            var value = Pub.ChangeValuePopup(100.0, "일괄 속도 변경");

            for (int i = 0; i < this.bsPosData.Count; i++)
            {
                this.bsPosData.Position = i;
                var drv = this.bsPosData.Current as DataRowView;
                if (drv == null) return;
                var dr = drv.Row as DataSet1.MCModelRow;
                dr.Speed = value;
                dr.EndEdit();
            }
        }

        private void toolStripButton2_Click_2(object sender, EventArgs e)
        {
            var dlg = Util.MsgQ("모든 이동좌표의 가(감)속도를 일괄 변경하시겠습니까?");
            if (dlg != System.Windows.Forms.DialogResult.Yes) return;
            var value = Pub.ChangeValuePopup(100.0, "일괄 가(감)속도 변경");

            for (int i = 0; i < this.bsPosData.Count; i++)
            {
                this.bsPosData.Position = i;
                var drv = this.bsPosData.Current as DataRowView;
                if (drv == null) return;
                var dr = drv.Row as DataSet1.MCModelRow;
                dr.SpeedAcc = value;
                dr.EndEdit();
            }
        }

        private void toolStripButton3_Click_1(object sender, EventArgs e)
        {
            var dlg = Util.MsgQ("모든 이동좌표의 감속도를 일괄 변경하시겠습니까?");
            if (dlg != System.Windows.Forms.DialogResult.Yes) return;
            var value = Pub.ChangeValuePopup(0, "일괄 감속도 변경");

            for (int i = 0; i < this.bsPosData.Count; i++)
            {
                this.bsPosData.Position = i;
                var drv = this.bsPosData.Current as DataRowView;
                if (drv == null) return;
                var dr = drv.Row as DataSet1.MCModelRow;
                dr.SpeedDcc = value;
                dr.EndEdit();
            }
        }
    }
}

