using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using JWH;
using JWH.MONGODB;
using MongoDB.Bson;
using Telerik.WinControls.Data;
using Telerik.WinControls.UI;
using static JWH.MONGODB.FDCMongoDB;

namespace DDUtilityApp.MONGO
{

    public partial class FrmFDCMongo : Form
    {

        public string EquipmentID { get; set; } = string.Empty;

        public string VID { get; set; } = string.Empty;

        public DateTime DateTimeStart { get; set; } = DateTime.Now.Date;

        public DateTime DateTimeEnd { get; set; } = DateTime.Now.AddDays(1).Date;

        public FrmFDCMongo()
        {
            InitializeComponent();

            this.SetLayout();
            this.SetEventHandler();
        }

        private void SetLayout()
        {
            this.Text = $"FDC MongoDB";

            this.dpStart.CustomFormat = "yyyy-MM-dd HH:mm";
            this.dpStart.Format = DateTimePickerFormat.Custom;
            this.dpStart.Value = this.DateTimeStart;
            this.dpEnd.CustomFormat = "yyyy-MM-dd HH:mm";
            this.dpEnd.Format = DateTimePickerFormat.Custom;
            this.dpEnd.Value = this.DateTimeEnd;
            this.pbarCollectionSize.Visible = false;
            this.lblProgressValue.Visible = false;

            this.tree.ShowLines = true;
            this.tree.ShowRootLines = true;

            this.GridSetting();
        }

        private void SetEventHandler()
        {
            this.Shown += this.FrmFDC_Shown;

            this.tboxEquipmentID.KeyDown += this.TboxEquipmentID_KeyDown;
            this.btnEquipmentFind.Click += this.BtnEquipmentFind_Click;
            this.dpStart.ValueChanged += this.DpStart_ValueChanged;
            this.dpEnd.ValueChanged += this.DpEnd_ValueChanged;
            this.btnRefresh.Click += this.BtnRefresh_Click;
            this.btnGetCollectionSizeStart.Click += this.BtnGetCollectionSizeStart_Click;

            this.tree.SelectedNodeChanged += this.Tree_SelectedNodeChanged;
        }

        #region [ Event ] =====================================================

        private void FrmFDC_Shown(object sender, EventArgs e)
        {
            this.SetTree();
            if (string.IsNullOrEmpty(this.EquipmentID)) return;

            this.tboxEquipmentID.Text = this.EquipmentID;
            this.dpStart.Value = this.DateTimeStart;
            this.dpEnd.Value = this.DateTimeEnd;
            this.BtnEquipmentFind_Click(null, null);
        }

        private void DpStart_ValueChanged(object sender, EventArgs e)
        {
            this.DateTimeStart = this.dpStart.Value;
        }

        private void DpEnd_ValueChanged(object sender, EventArgs e)
        {
            this.DateTimeEnd = this.dpEnd.Value;
        }

        private void BtnRefresh_Click(object sender, EventArgs e)
        {
            DateTime timeStart = DateTime.Now;
            List<TraceCollection> data = null;
            try
            {
                string collectionName = $"{this.EquipmentID}.{this.VID}";
                //FDCMongoDB.GetCollectionColumns(collectionName);

                this.Cursor = Cursors.WaitCursor;
                this.ssName.Text = "GRID";

                DateTime dtStart = this.DateTimeStart;
                DateTime dtEnd = this.DateTimeEnd;
                data = FDCMongoDB.GetCollectionData(collectionName, dtStart, dtEnd);
                timeStart = this.StatusLabelDisplay(this.ssStatus01, "수집", timeStart, DateTime.Now);

                this.grid.AutoBinding(data.ToArray());
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex, true);
            }
            finally
            {
                this.StatusLabelDisplay(this.ssStatus02, "출력", timeStart, DateTime.Now);
                this.ssMessage.Text = $"RowCount is {data?.Count.ToString("#,##0")}";
                this.Cursor = Cursors.Default;
            }
        }

        private void TboxEquipmentID_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                this.BtnEquipmentFind_Click(null, null);
        }

        private void BtnEquipmentFind_Click(object sender, EventArgs e)
        {
            RadTreeNode node = this.tree.Find(x => x.Name.StartsWith(this.tboxEquipmentID.Text));
            if (node != null)
            {
                this.tree.ClearSelection();
                node.Selected = true;
                node.ExpandAll();
            }
        }

        private void BtnGetCollectionSizeStart_Click(object sender, EventArgs e)
        {
            if (FDCMongoDB.GetCollectionSize_Flag)
            {
                this.GetCollectionSize_Complete();
                return;
            }

            SaveFileDialog dlg = new SaveFileDialog();
            dlg.Title = "FDC Collection Infomation";
            dlg.Filter = "CSV|*.csv";
            dlg.FilterIndex = 0;
            dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            dlg.FileName = $"FDC_Collection-{DateTime.Now.ToString("yyyyMMddHHmm")}.csv";
            if (dlg.ShowDialog() != DialogResult.OK) return;

            this.lblProgressValue.Text = "";
            this.lblProgressValue.Visible = true;
            this.pbarCollectionSize.Visible = true;
            this.btnGetCollectionSizeStart.Text = "Stop";
            FDCMongoDB.GetCollectionSize(dlg.FileName, this.GetCollectionSize_Complete, this.pbarCollectionSize, this.lblProgressValue);
        }

        private void GetCollectionSize_Complete(string filename = "")
        {
            FDCMongoDB.GetCollectionSize_Flag = false;
            this.btnGetCollectionSizeStart.Text = "Start";
            this.pbarCollectionSize.Visible = false;
            this.lblProgressValue.Visible = false;

            if (string.IsNullOrEmpty(filename)) return;
            Process.Start(filename);
        }

        #endregion

        #region [ Method ] ====================================================

        private DateTime StatusLabelDisplay(RadLabelElement control, string name, DateTime start, DateTime end)
        {
            TimeSpan span = end.Subtract(start);

            StringBuilder sb = new StringBuilder();
            if (!string.IsNullOrEmpty(name)) sb.Append($"{name} ");
            sb.Append($"[{span.Seconds}.{span.Milliseconds.ToString("D3")}sec] ");
            sb.Append($"{start.ToString("HH:mm:ss.fff")}~{end.ToString("HH:mm:ss.fff")}");
            control.Text = sb.ToString();

            return end;
        }

        #endregion

        #region [ Tree: Equipment & VID List ] ================================

        private void SetTree()
        {
            DateTime timeStart = DateTime.Now;
            SortedDictionary<string, List<string>> dicEquipment = new SortedDictionary<string, List<string>>();
            try
            {
                this.Cursor = Cursors.WaitCursor;
                this.ssName.Text = "TREE";

                timeStart = DateTime.Now;
                List<BsonDocument> lst = FDCMongoDB.GetListCollection();

                timeStart = this.StatusLabelDisplay(this.ssStatus01, "수집", timeStart, DateTime.Now);
                foreach (BsonDocument doc in lst)
                {
                    string[] values = doc.GetElement("name").Value.ToString().Split(new char[] { '=', '.' });
                    if (values.Length != 2)
                    {
                        XLogger.Instance.Error($"Split Fail: {doc.GetElement(0)}");
                        continue;
                    }
                    string name = values[0];
                    string vid = values[1];

                    if (!dicEquipment.ContainsKey(name))
                        dicEquipment[name] = new List<string>();
                    dicEquipment[name].Add(vid);
                }

                DataTable dt = this.GetMesEquipment();
                this.tree.Nodes.Clear();
                foreach (string equipmentID in dicEquipment.Keys)
                {
                    string text = equipmentID;
                    RadTreeNode nodeParent = null;

                    DataRow[] drEquipmnet = dt.Select($"EQUIPMENTID='{equipmentID}'");
                    if (drEquipmnet?.Length > 0)
                    {
                        string facilityName = drEquipmnet[0]["FACILITYNAME"].ToString();
                        string equipmentName = drEquipmnet[0]["DESCRIPTION"].ToString();
                        string segmentID = drEquipmnet[0]["PROCESSSEGMENTID"].ToString();
                        string segmentName = drEquipmnet[0]["PROCESSSEGMENTNAME"].ToString();

                        if (!this.tree.Nodes.Contains(facilityName))
                            this.tree.Nodes.Add(facilityName).Name = facilityName;
                        nodeParent = this.tree.Nodes[facilityName];

                        //if (!nodeParent.Nodes.Contains(segmentID))
                        //    nodeParent.Nodes.Add($"[{segmentID}] {segmentName}").Name = segmentID;
                        //nodeParent = nodeParent.Nodes[segmentID];

                        text = $"[{equipmentID}] {equipmentName}({dicEquipment[equipmentID].Count})";
                    }

                    RadTreeNode node = new RadTreeNode(text);
                    node.Name = equipmentID;
                    if (nodeParent != null) nodeParent.Nodes.Add(node);
                    else this.tree.Nodes.Add(node);

                    foreach (string vid in dicEquipment[equipmentID])
                    {
                        RadTreeNode nodeVID = node.Nodes.Add(vid);
                        nodeVID.Name = $"{equipmentID}.{vid}";
                        nodeVID.Tag = $"{equipmentID}.{vid}";
                    }
                }

                this.tree.SortOrder = System.Windows.Forms.SortOrder.Ascending;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                this.StatusLabelDisplay(this.ssStatus02, "출력", timeStart, DateTime.Now);
                this.ssMessage.Text = $"Equipment is {dicEquipment.Count.ToString("#,##0")}";
                this.Cursor = Cursors.Default;
            }
        }

        private DataTable GetMesEquipment()
        {
            SqlConnection sqlConnection = null;
            DataSet ds = null;
            DataTable dt = null;
            try
            {
                string connectionString = string.Empty;
                StringBuilder query = new StringBuilder();
                query.AppendLine($" SELECT  A.SITEID, ");
                query.AppendLine($"         A.FACILITYID, ");
                query.AppendLine($"         D.FACILITYNAME, ");
                query.AppendLine($"         B.PROCESSSEGMENTID, ");
                query.AppendLine($"         B.PROCESSSEGMENTNAME, ");
                query.AppendLine($"         A.SUBCATEGORY, ");
                query.AppendLine($"         C.EQUIPMENTID AS MAINEQUIPMENTID, ");
                query.AppendLine($"         C.EQUIPMENTNAME AS MAINEQUIPMENTNAME, ");
                query.AppendLine($"         A.EQUIPMENTID, ");
                query.AppendLine($"         A.EQUIPMENTNAME, ");
                query.AppendLine($"         A.DESCRIPTION, ");
                query.AppendLine($"         A.OPERATIONMODE, ");
                query.AppendLine($"         A.CONTROLMODE, ");
                query.AppendLine($"         A.LASTTRACKINLOTID, ");
                query.AppendLine($"         A.LASTTRACKOUTLOTID, ");
                query.AppendLine($"         A.MAKER, ");
                query.AppendLine($"         A.EQPSTATE, ");
                query.AppendLine($"         A.LOCATION ");
                query.AppendLine($" FROM    CIM_EQUIPMENT A (nolock) ");
                query.AppendLine($"         INNER JOIN  CIM_PROCESSSEGMENT B (nolock) ON A.PROCESSSEGMENTID = B.PROCESSSEGMENTID AND A.SITEID = B.SITEID ");
                query.AppendLine($"         INNER JOIN  CIM_EQUIPMENT C (nolock) ON A.PARENTID = C.EQUIPMENTID AND A.SITEID = C.SITEID ");
                query.AppendLine($"         INNER JOIN  CIM_FACILITY D (nolock) ON A.PHYSICALLOCATION = D.FACILITYID AND a.SITEID = d.SITEID ");
                query.AppendLine($" WHERE   A.SITEID='1130' ");

                connectionString = $@"server=192.168.8.232;database=ddmes;uid=DDB2MESAdmin;pwd=Yhqe4csJXJ4W5$%;";
                sqlConnection = new SqlConnection();
                sqlConnection.ConnectionString = connectionString;
                sqlConnection.Open();

                SqlCommand sqlCommand = new SqlCommand();
                sqlCommand.Connection = sqlConnection;
                sqlCommand.CommandType = CommandType.Text;
                sqlCommand.CommandText = query.ToString();

                ds = new DataSet();
                SqlDataAdapter sqlAdapter = new SqlDataAdapter(sqlCommand);
                sqlAdapter.Fill(ds);
                sqlConnection.Close();

                if (ds != null && ds.Tables.Count > 0) dt = ds.Tables[0];
                return dt;
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
                return null;
            }
            finally
            {
                if (sqlConnection != null && sqlConnection.State != ConnectionState.Closed)
                {
                    sqlConnection.Close();
                    sqlConnection.Dispose();
                }
            }
        }

        private void Tree_SelectedNodeChanged(object sender, RadTreeViewEventArgs e)
        {
            if (e.Node == null || e.Node.Tag == null) return;

            string[] values = e.Node.Tag.ToString().Split('.');
            if (values.Length != 2) return;

            this.EquipmentID = values[0];
            this.VID = values[1];
            this.BtnRefresh_Click(null, null);
        }

        #endregion

        #region [ Grid: TraceCollection ] =====================================

        private void GridSetting()
        {
            this.grid.MultiSelect = true;
            this.grid.Columns.Clear();
            this.grid.TableElement.RowHeight = 20;
            this.grid.HeaderTextToTitleCase = false;

            this.grid.AddColumn("EVENTTIME", "EventTime");
            this.grid.AddColumn("VIDName");
            this.grid.AddColumn("Value");
            this.grid.AddColumn("Sign");
            this.grid.AddColumn("LotID");
            this.grid.AddColumn("MaterialID");
            this.grid.AddColumn("ProductID");
            this.grid.AddColumn("Recipe");
            this.grid.AddColumn("UnitNO");
            this.grid.AddColumn("ProcessID");
            this.grid.AddColumn("VORNR");
            this.grid.AddColumn("UnitState");
            this.grid.AddColumn("Step");
            this.grid.AddColumn("LowerSV");
            this.grid.AddColumn("UpperSV");
            this.grid.AddColumn("CarrierId");
            this.grid.AddColumn("PanelId");
            this.grid.AddColumn("Position");
            this.grid.AddColumn("MarkingId");
            this.grid.AddColumn("MongGoUnitName");
        }

        #endregion

    }

}
