using AR;
using FarPoint.CalcEngine;
using FarPoint.Excel;
using FarPoint.Excel.EntityClassLibrary.DrawingEx;
using NetOffice.OfficeApi.Enums;
using NetOffice.OutlookApi;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Entity.Core.Mapping;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FPJ0000.JobReport_
{
    public partial class fJobProcessSelect : Form
    {
        string FullName = string.Empty;
        string GroupCode = "15";
        bool IsAdmin = false;

        public fJobProcessSelect(string fullname, bool isAdmin = false)
        {
            InitializeComponent();
            this.IsAdmin = isAdmin;
            this.FullName = fullname;
            this.dsJobReport.Common.TableNewRow += Common_TableNewRow;
            this.FormClosing += FJobProcessManager_FormClosing;
            this.KeyPreview = true;

            this.KeyDown += (s1, e1) => {
                if (e1.KeyCode == Keys.Escape) this.Close();
            };

            // 이벤트 핸들러 연결
            treeView1.ItemDrag += TreeView1_ItemDrag;
            treeView1.DragEnter += TreeView1_DragEnter;
            treeView1.DragDrop += TreeView1_DragDrop;

            //var auth = (FCOMMON.info.Login.level >= 5 || isAdmin);
            btSave.Visible = isAdmin;
            btDelete.Visible = isAdmin;
            btImport.Visible = isAdmin;
            panel1.Visible = isAdmin;
            btRefreshTreeview.Visible = isAdmin;
            lbWarningManager.Visible = isAdmin;
            lbWarningUser.Visible = !isAdmin;
            btSelect.Visible = !isAdmin;

            if (fullname.isEmpty() == false)
            {
                this.Text = $"작업형태 선택(기존값:{fullname})";
                var buf = fullname.Split('|');
                var prc = buf[0].Trim();
                this.tbProcessE.Text = prc;
                this.tbProcessI.Text = prc;
                this.tbProcessI.Enabled = false;
                this.tbProcessE.Enabled = false;
            }
        }

        private void TreeView1_ItemDrag(object sender, ItemDragEventArgs e)
        {
            // Ctrl 키가 눌린 상태면 복사, 아니면 이동
            if (IsAdmin == false) return;
            DragDropEffects effect = (ModifierKeys == Keys.Control) ?
                DragDropEffects.Copy : DragDropEffects.Move;
            DoDragDrop(e.Item, effect);
        }

        private void TreeView1_DragEnter(object sender, DragEventArgs e)
        {
            if (IsAdmin == false) return;
            // 드래그한 항목이 TreeNode인 경우에만 허용
            if (e.Data.GetDataPresent(typeof(TreeNode)))
            {
                // Ctrl 키가 눌린 상태면 복사 효과 표시
                e.Effect = (ModifierKeys == Keys.Control) ?
                    DragDropEffects.Copy : DragDropEffects.Move;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void TreeView1_DragDrop(object sender, DragEventArgs e)
        {
            if (this.bn.Enabled == false)
            {
                AR.UTIL.MsgE("권한이 없어 drag & drop 을 사용할 수 없습니다");
                return;
            }
            if (IsAdmin == false) return;
            // 드롭된 위치의 노드 찾기
            Point pt = treeView1.PointToClient(new Point(e.X, e.Y));
            TreeNode destinationNode = treeView1.GetNodeAt(pt);
            TreeNode draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode));

            // 자기 자신이나 자식 노드로는 이동할 수 없음
            if (destinationNode == null || draggedNode == destinationNode ||
                IsChildNode(draggedNode, destinationNode))
            {
                return;
            }

            var dr = draggedNode.Tag as dsJobReport.CommonRow;

            if (e.Effect == DragDropEffects.Move)    //이동한다면 기존 데이터는 삭제한다
            {
                draggedNode.Remove();
            }

            var inseritem = e.Effect == DragDropEffects.Copy;

            if (draggedNode.Level == 1)  //분류를 움직이고 있다
            {
                if (destinationNode.Level == 2)
                {
                    var idx = destinationNode.Parent.Parent.Nodes.Add((TreeNode)draggedNode.Clone());
                    var cnd = destinationNode.Parent.Parent.Nodes[idx];
                    UpdateParentInfo(cnd, inseritem);
                }
                else if (destinationNode.Level == 1)
                {
                    var idx = destinationNode.Parent.Nodes.Add((TreeNode)draggedNode.Clone());
                    var cnd = destinationNode.Parent.Nodes[idx];
                    UpdateParentInfo(cnd, inseritem);
                }
                else
                {
                    var idx = destinationNode.Nodes.Add((TreeNode)draggedNode.Clone());
                    var cnd = destinationNode.Nodes[idx];
                    UpdateParentInfo(cnd, inseritem);
                }
                //AR.UTIL.MsgE("카테고리 이동은 불가 합니다");

            }
            else
            {     // 노드 이동
                if (destinationNode.Level > 2)
                {
                    UTIL.MsgE("최하위 레벨이하로는 이동할 수 없습니다");
                }
                else if (destinationNode.Level > 1)
                {
                    var idx = destinationNode.Parent.Nodes.Add((TreeNode)draggedNode.Clone());
                    var cnd = destinationNode.Parent.Nodes[idx];
                    UpdateParentInfo(cnd, inseritem);
                }
                else
                {
                    var idx = destinationNode.Nodes.Add((TreeNode)draggedNode.Clone());
                    var cnd = destinationNode.Nodes[idx];
                    UpdateParentInfo(cnd, inseritem);
                }
            }

        }
        void UpdateParentInfo(TreeNode cnd, bool newitem)
        {




            if (cnd.Level == 2)  //최하위
            {
                var grp = cnd.Parent.Text;
                var prc = cnd.Parent.Parent.Text;

                //신규로추가를 해준다
                if (newitem)
                {
                    dsJobReport.CommonRow ndr = this.dsJobReport.Common.NewCommonRow();
                    ndr.svalue2 = prc;
                    ndr.svalue = grp;
                    ndr.memo = cnd.Text;
                    ndr.wuid = FCOMMON.info.Login.no;
                    ndr.wdate = DateTime.Now;
                    ndr.grp = this.GroupCode;
                    ndr.code = makenewcode();
                    this.dsJobReport.Common.AddCommonRow(ndr);
                    cnd.Tag = ndr;
                }
                else
                {
                    //기존정보를 업데이트한다
                    var dr = cnd.Tag as dsJobReport.CommonRow;
                    dr.svalue = grp;
                    dr.svalue2 = prc;
                    dr.EndEdit();

                }

            }
            else if (cnd.Level == 1) //분류(하위항목업데이트필요)
            {
                var prc = cnd.Parent.Text;
                foreach (TreeNode nd in cnd.Nodes)
                {

                    //신규로추가를 해준다
                    if (newitem)
                    {
                        dsJobReport.CommonRow ndr = this.dsJobReport.Common.NewCommonRow();
                        ndr.svalue2 = prc;
                        ndr.svalue = cnd.Text;
                        ndr.memo = nd.Text;
                        ndr.wuid = FCOMMON.info.Login.no;
                        ndr.wdate = DateTime.Now;
                        ndr.grp = this.GroupCode;
                        ndr.code = makenewcode();
                        this.dsJobReport.Common.AddCommonRow(ndr);
                        nd.Tag = cnd;
                    }
                    else
                    {
                        var dr = nd.Tag as dsJobReport.CommonRow;
                        dr.svalue2 = prc;
                        dr.EndEdit();
                    }
                }
            }
            else if (cnd.Level == 0) //프로세스(하위항모업데이트필요)
            {

            }

            this.treeView1.SelectedNode = cnd;
            this.treeView1.SelectedNode.EnsureVisible();
            this.treeView1.Focus();

        }

        private bool IsChildNode(TreeNode parent, TreeNode node)
        {
            // 대상 노드가 현재 노드의 자식인지 확인
            if (node.Parent == null) return false;
            if (node.Parent == parent) return true;
            return IsChildNode(parent, node.Parent);
        }

        private void FJobProcessManager_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (haschanged() == true)
            {
                var dlg = UTIL.MsgQ("변경된 내용이 있습니다 그래도 화면을 닫을까요?");
                if (dlg != DialogResult.Yes)
                {
                    e.Cancel = true;
                    return;
                }
            }

        }
        bool haschanged()
        {
            var dt = this.dsJobReport.Common.GetChanges();
            if (dt == null) return false;
            if (dt.Rows.Count < 1) return false;
            return true;
        }

        private void Common_TableNewRow(object sender, DataTableNewRowEventArgs e)
        {
            e.Row["wdate"] = DateTime.Now;
            e.Row["wuid"] = FCOMMON.info.Login.no;
            e.Row["gcode"] = FCOMMON.info.Login.gcode;
            e.Row["grp"] = this.GroupCode;
        }

        private void commonBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {
            this.Validate();
            this.bs.EndEdit();

            if (this.haschanged() == false)
            {
                UTIL.MsgI("변경된 내용이 없습니다");
                return;
            }
            try
            {
                var cnt = this.tam.UpdateAll(this.dsJobReport);
                AR.UTIL.MsgI($"{cnt}건의 자료가 업데이트 되었습니다");
                RefreshTreeview();
            }
            catch (System.Exception ex)
            {
                UTIL.MsgE(ex.Message);
            }
        }

        private void RefreshData()
        {
            try
            {
                var fullname = this.FullName.Split('|');
                var pc = fullname[0].ToString();
                var grp = fullname.Length > 2 ? fullname[1].Trim() : string.Empty;
                if (pc.isEmpty())
                {
                    this.ta.Fill(this.dsJobReport.Common, FCOMMON.info.Login.gcode, GroupCode);
                }   
                else
                {
                    this.ta.FillByJobProcess(this.dsJobReport.Common, FCOMMON.info.Login.gcode, GroupCode, pc);
                    if(this.dsJobReport.Common.Any()==false)
                    {
                        AR.UTIL.MsgE($"입력된 [{pc}]에 해당하는 분류가 없어 전체목록을 조회 합니다\n분류표는 관리->업무일지->업무형태 설정 화면에서 입력이 가능합니다");
                        this.ta.Fill(this.dsJobReport.Common, FCOMMON.info.Login.gcode, GroupCode);
                    }
                }
                    

                this.commonDataGridView.AutoResizeColumns();

        
            }
            catch (System.Exception ex)
            {
                AR.UTIL.MsgE(ex.Message);
            }

            RefreshTreeview();

        }

        private void fJobProcessManager_Load(object sender, EventArgs e)
        {
            RefreshData();
            this.Show();
            System.Windows.Forms.Application.DoEvents();
            this.treeView1.Focus();

            int curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
            this.bn.Enabled = (curLevel >= 5);
            this.button2.Enabled = bn.Enabled;
            this.btAdd.Enabled = bn.Enabled;
            this.btEdit.Enabled = bn.Enabled;
            this.groupBox3.Enabled = bn.Enabled;
            this.groupBox4.Enabled = bn.Enabled;
            this.commonDataGridView.ReadOnly = !bn.Enabled;
          
        }
        void RefreshTreeview()
        {
            this.treeView1.Nodes.Clear();
            //dsJobReport.AcceptChanges();
            var items = this.dsJobReport.Common.Where(t => t.RowState != DataRowState.Detached && t.RowState != DataRowState.Deleted && string.IsNullOrEmpty(t.svalue));
            foreach (var item in items)
            {
                item.svalue = "N/A";
                item.EndEdit();
            }

            //선택된 항목이 있따면 해당 항목을 선택해준다.
            var selectedpath = this.FullName.Split('|');
            var bAutoselect = selectedpath.Length == 3;
            var SelPRC = bAutoselect ? selectedpath[0].Trim() : string.Empty;
            var SelGRP = bAutoselect ? selectedpath[1].Trim() : string.Empty;
            var SelITM = bAutoselect ? selectedpath[2].Trim() : string.Empty;
            if (SelPRC.isEmpty()) SelPRC = "N/A";

            var grp_process = dsJobReport.Common.OrderBy(t => t.svalue2).GroupBy(t => t.svalue2);
            TreeNode autoSelectNode = null;
            foreach (var prc in grp_process)
            {
                var prcname = prc.Key;
                if (prcname.isEmpty()) prcname = "N/A";
                if (prcname.Equals("(N/A)")) prcname = "N/A";

                var nd = treeView1.Nodes.Add(prcname, prcname); //add process node
                var grp_jobtype = prc.OrderBy(t => t.svalue).GroupBy(t => t.svalue);
                foreach (var grp in grp_jobtype) //job type
                {
                    var nd2 = nd.Nodes.Add(grp.Key, grp.Key);
                    var grpname = grp.Key;
                    foreach (var item in grp.OrderBy(t => t.memo))
                    {
                        var nd3 = nd2.Nodes.Add(item.memo, item.memo);     //job item
                        if (prcname.Equals("N/A"))
                            nd3.ForeColor = Color.DimGray;
                        else
                            nd3.ForeColor = Color.Black;
                        nd3.Tag = item;

                        if (bAutoselect)
                        {
                            if (prcname.Equals(SelPRC) && grpname.Equals(SelGRP) && item.memo.Equals(SelITM))
                            {
                                autoSelectNode = nd3;
                            }
                        }
                    }
                }
            }
            this.treeView1.CollapseAll();
            groupBox3.Enabled = false;
            if (autoSelectNode != null)
            {
                this.treeView1.SelectedNode = autoSelectNode;
                this.treeView1.SelectedNode.EnsureVisible();
                this.treeView1.SelectedNode.Expand(); 
                this.treeView1.Focus();

            }
            else
            {
       
                if(this.treeView1.Nodes.Count > 0)
                    this.treeView1.Nodes[0].Expand();
            }




        }

        private void tbFind_KeyDown(object sender, KeyEventArgs e)
        {
            var search = tbFind.Text.Trim();
            if (e.KeyCode == Keys.Enter)
            {
                try
                {
                    var cols = new string[] { "svalue", "memo" };
                    var filterstring = "";
                    foreach (var col in cols)
                    {
                        if (filterstring.Length > 0) filterstring += $" or ";
                        filterstring += $"{col} like '%{search}%'";
                    }
                    if (search.isEmpty())
                    {
                        this.bs.Filter = "";
                        tbFind.BackColor = Color.White;
                    }
                    else
                    {
                        this.bs.Filter = filterstring;
                        tbFind.BackColor = Color.Lime;
                    }
                }
                catch (System.Exception ex)
                {
                    AR.UTIL.MsgE(ex.Message);
                    tbFind.BackColor = Color.HotPink;
                }
                tbFind.Focus();
                tbFind.SelectAll();
            }

        }

        private void groupBox2_Enter(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            RefreshTreeview();
        }

        private void btEdit_Click(object sender, EventArgs e)
        {
            //edit
            var prc = tbProcessE.Text.Trim();
            var grp = tbTypeE.Text.Trim();
            var item = tbItemE.Text.Trim();

            if (item.isEmpty())
            {
                UTIL.MsgE("형태는 반드시 입력되어야 합니다");
                tbItemE.Focus();
                return;
            }
            if (prc.isEmpty())
            {
                UTIL.MsgE("프로세스가 입력되지 않았습니다");
                tbProcessE.Focus();
                return;
            }

            var nd = this.treeView1.SelectedNode;
            if (nd == null)
            {
                UTIL.MsgE("선택된 노드가 없습니다");
                return;
            }
            if (nd.Tag == null)
            {
                UTIL.MsgE("선택노드에 정보가 없습니다\n개발자 문의");
                return;
            }

            //동일데이터가있는지확인
            var exist = this.dsJobReport.Common.Where(t => t.RowState != DataRowState.Deleted && t.svalue2.Equals(prc) && t.svalue.Equals(grp) && t.memo.Equals(item)).Any();
            if (exist)
            {
                UTIL.MsgE("동일한 항목이 존재합니다 / 확인 후 다시 진행 하세요");
                return;
            }


            var dr = nd.Tag as dsJobReport.CommonRow;
            if (dr == null) return;

            var changecate = (dr.svalue2.Equals(prc) == false || dr.svalue.Equals(grp) == false);

            dr.svalue2 = prc;
            dr.svalue = grp;
            dr.memo = item;
            dr.EndEdit();

            //카테고리가 변경되었다면 위치를 이동시켜야한다
            nd.Remove(); //선택노드를 삭제한다.
            AddNode(prc,grp, item, dr);



        }
        void AddNode(string prc, string grp, string item, dsJobReport.CommonRow dr)
        {
            //프로세스 노드 선택
            TreeNode tn_grp = null;
            TreeNode tn_prc = null;
            if (grp.isEmpty()) grp = "N/A";
            if (prc.isEmpty()) prc = "N/A";

            var prc_nodes = this.treeView1.Nodes.Find(prc, false);
            if (prc_nodes.Any() == false)
            {
                tn_prc = treeView1.Nodes.Add(prc, prc); //신규노드추가
            }
            else
            {
                tn_prc = prc_nodes.First(); //첫번째 노드로 변경
            }


            var grp_nodes = tn_prc.Nodes.Find(grp, false);
            if (grp_nodes.Any() == false)
            {
                tn_grp = tn_prc.Nodes.Add(grp, grp); //신규노드추가
            }
            else
            {
                tn_grp = grp_nodes.First(); //첫번째 노드로 변경
            }



            //아이템노드확인
            TreeNode tn_item = null;
            var item_nodes = tn_grp.Nodes.Find(item, false);
            if (item_nodes.Any() == false)
            {
                tn_item = tn_grp.Nodes.Add(item, item); //신규노드추가
            }
            else
            {
                tn_item = item_nodes.First();
                //동일한 노드이다
            }

            tn_item.Tag = dr;
            treeView1.SelectedNode = tn_item;
            treeView1.SelectedNode.EnsureVisible();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            //add
            var grp = tbTypeA.Text.Trim();
            var item = tbItemA.Text.Trim();
            var prc = tbProcessI.Text.Trim();

            if (prc.isEmpty())
            {
                UTIL.MsgE("프로세스가 입력되지 않았습니다");
                tbProcessI.Focus();
                return;
            }


            if (item.isEmpty())
            {
                UTIL.MsgE("형태는 반드시 입력되어야 합니다");
                tbItemA.Focus();
                return;
            }

            //동일데이터가있는지확인
            var exist = this.dsJobReport.Common.Where(t => t.RowState != DataRowState.Deleted && t.svalue2.Equals(prc) && t.svalue.Equals(grp) && t.memo.Equals(item)).Any();
            if (exist)
            {
                UTIL.MsgE("동일한 항목이 존재합니다 / 확인 후 다시 진행 하세요");
                tbItemA.Focus();
                tbItemA.SelectAll();
                return;
            }
            var dr = this.dsJobReport.Common.NewCommonRow();
            dr.svalue2 = prc;
            dr.svalue = grp;
            dr.memo = item;
            dr.wuid = FCOMMON.info.Login.no;
            dr.wdate = DateTime.Now;
            dr.grp = this.GroupCode;
            dr.code = makenewcode();
            this.dsJobReport.Common.AddCommonRow(dr);

            AddNode(prc, grp, item, dr);

            tbItemA.Focus();
            tbItemA.SelectAll();
        }

        string makenewcode()
        {
            string lastcodename = "";
            var lastcodedr = dsJobReport.Common.OrderByDescending(t => t.code).FirstOrDefault();
            if (lastcodedr != null) lastcodename = lastcodedr.code;
            int newnum = 0;
            int codenameleng = lastcodename.Length;
            if (codenameleng == 0) codenameleng = 4;

            if (int.TryParse(lastcodename, out int lastcodenum) == false)
            {
                //숫자로되어있지 않다
                newnum = 1;// newnum.PadLeft(codenameleng, '0');
            }
            else
            {
                //숫자로되어있으니 +1해서 처리한다.
                newnum = (lastcodenum + 1);

            }
            var newnumstr = newnum.ToString().PadLeft(codenameleng, '0');

            return newnumstr;
        }

        private void tv_AfterSelect(object sender, TreeViewEventArgs e)
        {
            label8.Text = "Path://";
            var tn = this.treeView1.SelectedNode;
            if (tn == null) return;
            if (tn.Tag == null) return;

            this.label8.Text = tn.FullPath;

            var dr = tn.Tag as dsJobReport.CommonRow;
            if (dr == null) return;
            tbTypeE.Text = dr.svalue;
            tbTypeA.Text = dr.svalue;

            tbItemE.Text = dr.memo;
            tbItemA.Text = dr.memo;

            tbProcessE.Text = dr.svalue2;
            tbProcessI.Text = dr.svalue2;

            groupBox3.Enabled = true;
            groupBox3.Text = $"선택자료 편집({dr.idx})";

        }

        private void tbItemA_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                btAdd.PerformClick();
        }

        private void tbItemE_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                btEdit.PerformClick();
        }



        private void button2_Click_1(object sender, EventArgs e)
        {
            //선택노드삭제
            var nd = this.treeView1.SelectedNode;
            if (nd == null)
            {
                UTIL.MsgE("선택된 노드가 없습니다");
                return;
            }
            if (nd.Tag == null)
            {
                UTIL.MsgE("선택노드에 정보가 없습니다\n최하위 아이템을 선택하세요\n오류가 반복되면 개발사에 문의 하세요");
                return;
            }

            //동일데이터가있는지확인
            var dr = nd.Tag as dsJobReport.CommonRow;
            var grp = dr.svalue;
            var prc = dr.svalue2;
            var item = dr.memo;

            var exist = this.dsJobReport.Common.Where(t => t.RowState != DataRowState.Deleted &&
            t.svalue2.Equals(prc) && t.svalue.Equals(grp) && t.memo.Equals(item)).FirstOrDefault();

            if (exist == null)
            {
                UTIL.MsgE("해당 데이터를 찾지 못했습니다\n잠시 후 다시 시도하세요");
                return;
            }
            exist.Delete(); //            dsJobReport.Common.RemoveCommonRow(exist);
            nd.Remove();
            //RefreshTreeview();
        }

        private void btDelete_Click(object sender, EventArgs e)
        {
            RefreshTreeview();
        }

        private void btInsert_Click(object sender, EventArgs e)
        {

        }

        private void treeView1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                var nd = this.treeView1.SelectedNode;
                if (nd == null) return;

                if (nd.Level == 2)
                {
                    var dr = nd.Tag as dsJobReport.CommonRow;

                    nd.Remove();
                    dr.Delete();
                }
                else
                {
                    UTIL.MsgE("최하위 항목만 삭제 가능합니다");
                }

            }
        }

        private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (this.FullName.isEmpty()) return;

            //노드에서 항목 더블클릭
            var nd = this.treeView1.SelectedNode;
            if (nd == null) return;
            if (nd.Level < 1) return;
            var dr = nd.Tag as dsJobReport.CommonRow;
            if (dr == null) return;
            Feedback(dr);
        }

        private void btSelect_Click(object sender, EventArgs e)
        {
            //트리뷰항목 선택
            var nd = this.treeView1.SelectedNode;
            if (nd == null) return;
            if (nd.Level < 1)
            {
                UTIL.MsgE("최하위 항목을 선택하세요");
                return;
            }
            var dr = nd.Tag as dsJobReport.CommonRow;
            if (dr == null) return;
            Feedback(dr);
        }

        private void commonDataGridView_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            
        }

        void Feedback(dsJobReport.CommonRow dr)
        {
            var prc = dr.svalue2;
            var grp = dr.svalue;
            var itm = dr.memo;
            if (grp.isEmpty()) grp = "N/A";
            this.SelectedValue = $"{prc}|{grp}|{itm}";
            DialogResult = DialogResult.OK;
        }

        public string SelectedValue { get; set; } = "";
        private void 클립보드에서ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if(this.haschanged())
            {
                AR.UTIL.MsgE("변경된 자료가 존재합니다.\n현재 자료를 저장하거나 화면을 다시 호출 하세요");
                return;
            }

            UTIL.MsgI("목록화면고 동일한 배치의 데이터를 클립보드에서 가져옵니다\n(항목/분류/프로세스)");
            var data = Clipboard.GetText();
            var lines = data.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
            var dlg = UTIL.MsgQ($"{lines.Length} 개의 데이터가 있습니다.\n\n입력 할까요?");
            if (dlg != DialogResult.Yes) return;

            var icnt = 0;
            var scnt = 0;
            var ecnt = 0;
            foreach (var line in lines)
            {
                var buf = line.Split(new char[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
                var item = buf[0].Trim();
                if (item.isEmpty())
                {
                    ecnt += 1;
                    continue;
                }
                var grp = buf.Length > 1 ? buf[1].Trim() : string.Empty;
                var prc = buf.Length > 2 ? buf[2].Trim() : string.Empty;

                //동일항목체크
                if (this.dsJobReport.Common.Where(t => t.RowState != DataRowState.Detached && t.RowState != DataRowState.Deleted &&
                t.memo.Equals(item) && t.svalue2.Equals(prc) && t.svalue.Equals(grp)).Any())
                {
                    scnt += 1;
                    continue;
                }

                icnt += 1;

                var dr = this.dsJobReport.Common.NewCommonRow();
                dr.svalue = grp;
                dr.svalue2 = prc;
                dr.memo = item;
                dr.wuid = FCOMMON.info.Login.no;
                dr.wdate = DateTime.Now;
                dr.grp = this.GroupCode;
                dr.code = makenewcode();
                this.dsJobReport.Common.AddCommonRow(dr);
            }

            var msg = $"가져오기 결과 입니다\n\n추가:{icnt}\n중복:{scnt}\n오류:{ecnt}";
            AR.UTIL.MsgI(msg);
            if (icnt > 0)
                RefreshTreeview();

        }
        private void 전체삭제ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dlg = UTIL.MsgQ("현재 목록 데이터를 삭제할까요?\n저장을 하면 최종 서버에 적용 됩니다");
            if (dlg != DialogResult.Yes) return;
            var cnt = 0;
            while (bs.Count > 0)
            {
                bs.RemoveCurrent();
                cnt += 1;
            }
            UTIL.MsgI($"{cnt}건의 자료가 삭제되었습니다\n저장버튼을 누르면 데이터베이스에 적용 됩니다");
        }

        private void 클립보드에내보내기ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var sb = new System.Text.StringBuilder();
            sb.AppendLine("항목\t분류\t프로세스");
            var filterdata = this.dsJobReport.Common.Select(this.bs.Filter, this.bs.Sort);
            var cnt = 0;
            foreach (dsJobReport.CommonRow dr in filterdata)
            {
                if (dr.RowState == DataRowState.Deleted || dr.RowState == DataRowState.Detached) continue;
                cnt += 1;
                sb.AppendLine($"{dr.memo}\t{dr.svalue}\t{dr.svalue2}");
            }
            Clipboard.SetText(sb.ToString());
            AR.UTIL.MsgI($"{cnt}건의 자료가 클립보드에 입력되었습니다\n엑셀등의 프로그램에서 Ctrl+V 하세요");
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            this.treeView1.ExpandAll();
        }

        private void button3_Click_1(object sender, EventArgs e)
        {
            this.treeView1.CollapseAll();
        }

        private void commonDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            //데이터그리드뷰 항목 더블클릭
            if (this.FullName.isEmpty()) return;

            var drv = bs.Current as DataRowView;
            if (drv == null) return;
            var dr = drv.Row as dsJobReport.CommonRow;
            if (dr == null) return;
            Feedback(dr);
        }
    }
}
