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

namespace CNAS_RunSync
{
    public partial class ucSyncShow : UserControl
    {
        private log4net.ILog log = log4net.LogManager.GetLogger("ucSyncShow");
        private SyncInstrumentItemInfo syncInstrumentItem = new SyncInstrumentItemInfo();
        private Dictionary<string, DataTable> dictSourceTables = new Dictionary<string, DataTable>();
        private Dictionary<string, DataRow> dictSource = new Dictionary<string, DataRow>();
        private Dictionary<string, Type> DictComboBox = new Dictionary<string, Type>();   //ComboBox数据源
        private List<string> lstIntOrDouble = new List<string>() {"等于","不等于","大于","小于","不大于","不小于" };
        private List<string> lstText = new List<string>() { "等于", "不等于", "包含", "不包含"};
        private Color FinedBackColor = Color.LightCyan;

        //需要存在一个仪器才能正常显示数据
        public ucSyncShow(SyncInstrumentItemInfo syncInstrumentItem)
        {
            InitializeComponent();

            dgvSyncData.AutoGenerateColumns = false;
            dgvSyncData.RowHeadersVisible = false;

            this.syncInstrumentItem = syncInstrumentItem;
        }

        private void ucSyncShow_Load(object sender, EventArgs e)
        {
            BindData();
        }

        private void BindData()
        {
            if (this.syncInstrumentItem == null) return;
            if (syncInstrumentItem.LstSyncPramas == null) return;
            if (syncInstrumentItem.SyncInstrumentDSInfo == null) return;
            if (syncInstrumentItem.SyncInstrumentDSInfo.LocalPath == null) return;
            if (syncInstrumentItem.SyncInstrumentDSInfo.InstrumentDataSourceType == DataSourceType.None) return;

            DictComboBox.Clear();
            dictSource.Clear();
            dictSourceTables.Clear();

            //加载相关数据
            //1.TableLayout中相关
            this.lblTitle.Text = string.Format("当前仪器：【{0}】", syncInstrumentItem.Code);

            //2.datagridview中绑定数据（绑定的是从数据源中读取的数据）
            //2.1 读取所有数据【会额外读取多余的数据，但如果后面用户想要维护更多映射字段，可以方便新增】
            //2.2 获取映射表中的数据

            InstrumentData instrumentData = InstrumentDataFact.CreateInstrumentDataSource(syncInstrumentItem.SyncInstrumentDSInfo.InstrumentDataSourceType, new object[] { syncInstrumentItem.SyncInstrumentDSInfo.LocalPath, syncInstrumentItem.SyncInstrumentDSInfo.UserId, syncInstrumentItem.SyncInstrumentDSInfo.UserPwd });
            dictSourceTables = instrumentData.GetInstrumentData();

            //2.2.1 根据映射表，创建datagridviewcolumn/和绑定数据列
            if (syncInstrumentItem.LstSyncPramas.Count <= 0) return;
            foreach (var item in syncInstrumentItem.LstSyncPramas)
            {
                AddDatagridColumn(dgvSyncData, item.SourceField, item.SourceField, 100);
            }
            AddDatagridColumn(dgvSyncData, "GridGuid", "GridGuid", 100, false);

            //2.2.2 根据数据源，构建datagridviewcell
            if (!dictSourceTables.ContainsKey(syncInstrumentItem.LstSyncPramas[0].SourceTable)) return;
            DataTable dtSource = dictSourceTables[syncInstrumentItem.LstSyncPramas[0].SourceTable];
            foreach (DataRow dr in dtSource.Rows)
            {
                DataGridViewRow dataGridViewRow = new DataGridViewRow();
                foreach (DataGridViewColumn dataGridViewColumn in dgvSyncData.Columns)
                {
                    if (dtSource.Columns.Contains(dataGridViewColumn.Name))
                        AddDataTextCell(dataGridViewRow, dataGridViewColumn, dr);
                }

                //添加GUID值
                string strGuid = Guid.NewGuid().ToString();
                DataGridViewTextBoxCell txtCell = new DataGridViewTextBoxCell
                {
                    Value = strGuid
                };
                dataGridViewRow.Cells.Add(txtCell);

                dgvSyncData.Rows.Add(dataGridViewRow);

                dictSource.Add(strGuid, dr);
            }

            //3.初始化查询相关内容
            //3.1 绑定Combobox数据源        
            foreach (DataColumn dc in dtSource.Columns)
            {
                if (syncInstrumentItem.LstSyncPramas.Where(s => s.SourceField == dc.ColumnName).LongCount<SyncParamasInfo>() > 0)
                    DictComboBox.Add(dc.ColumnName, dc.DataType);
            }
            BindingSource bsComboBox = new BindingSource
            {
                DataSource = DictComboBox
            };
            cmbColumns.DataSource = bsComboBox;
            cmbColumns.ValueMember = "Key";
            cmbColumns.DisplayMember = "Key";
        }

        private void AddDatagridColumn(DataGridView dgvShow,string strColumnName,string strColumnHeaderText,int Width,bool bVisible=true)
        {
            DataGridViewColumn Column = new DataGridViewColumn()
            {
                Name = strColumnName,
                HeaderText = strColumnHeaderText,
                Width = Width,
                Visible = bVisible,
                CellTemplate = new DataGridViewTextBoxCell()
             };
            //设置文本对齐方式
            Column.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            //设置该列背景颜色
            //Column.DefaultCellStyle.BackColor = Color.Red;
            dgvShow.Columns.Add(Column);
        }

        private void AddDataTextCell(DataGridViewRow dataGridViewRow, DataGridViewColumn dataGridViewColumn,DataRow dr)
        {
            DataGridViewTextBoxCell txtCell = new DataGridViewTextBoxCell();
            txtCell.Value = Convert.ToString(dr[dataGridViewColumn.Name]);
            dataGridViewRow.Cells.Add(txtCell);
        }

        private void btnRunData_Click(object sender, EventArgs e)
        {
            //根据映射信息上传数据到数据库中
            //DataTable dtSource = dictSourceTables[syncInstrumentItem.LstSyncPramas[0].SourceTable];

            //组织上传数据
            if (dgvSyncData.Columns.Count <= 0) return;

            DataTable dtReadySource = dictSourceTables[syncInstrumentItem.LstSyncPramas[0].SourceTable].Clone();
            
            foreach (DataGridViewRow dgvRow in dgvSyncData.Rows)
            {
                if (dgvRow.DefaultCellStyle.BackColor == FinedBackColor)
                {
                    string strGuid = dgvRow.Cells["GridGuid"].Value.ToString();
                    if (!dictSource.ContainsKey(strGuid)) continue;
                    DataRow dr = dictSource[strGuid];

                    DataRow drReady = dtReadySource.NewRow();
                    foreach (DataColumn dc in dtReadySource.Columns)
                    {
                        if (dr.Table.Columns.Contains(dc.ColumnName))
                            drReady[dc.ColumnName] = dr[dc.ColumnName];
                    }
                    dtReadySource.Rows.Add(drReady);
                }
            }
            if (dtReadySource.Rows.Count <= 0)
                MessageBox.Show("未能获得上传数据，请查询筛选后重试！");
            RunUpLoad(dtReadySource);
        }

        private void RunUpLoad(DataTable dtReadySource)
        {
            //根据映射字段获取准备上传的所有数据
            if (dtReadySource == null || dtReadySource.Rows.Count <= 0) return;

            //构建准备插入的数据
            DataTable dtTarget = CnasDataOperationFact.CnasDataOperation().GetCNASTablesStruct(syncInstrumentItem.LstSyncPramas[0].TargetTable, syncInstrumentItem);

            if (dtTarget.Columns.Count <= 0)
            {
                MessageBox.Show("未能成功读取CNAS数据库列，请检查数据库配置。");
                return;
            }

            string strErrorMsg = "";
            foreach (DataRow drSource in dtReadySource.Rows)
            {
                DataRow drNewTarget = dtTarget.NewRow();

                //遍历映射表，把所有字段插入到目标表中
                foreach (var item in syncInstrumentItem.LstSyncPramas)
                {
                    var strSourceField = item.SourceField;
                    var strTargetField = item.TargetField;

                    //当列名存在于数据表中时才能继续
                    if (dtReadySource.Columns.Contains(strSourceField) && dtTarget.Columns.Contains(strTargetField))
                    {
                        strErrorMsg=TestConvertValueToTarget(drNewTarget,drSource,strTargetField,strSourceField);
                        if (strErrorMsg != "")
                        {
                            MessageBox.Show(string.Format("发生数据转换错误，请重新配置映射字段或修改字段值。错误信息如下：{0}",strErrorMsg));
                            break;
                        }

                    }
                }
                dtTarget.Rows.Add(drNewTarget);

                if (strErrorMsg != "") break;
            }
            if (strErrorMsg != "") return;

            CnasDataCheck check = new CnasDataCheck
            {
                DtReadyInsert = dtTarget,
                SyncInstrumentItem = syncInstrumentItem,
                StrTableName = syncInstrumentItem.LstSyncPramas[0].TargetTable
            };
            check.CheckData();
            if (check.LstIllegalMsg != null && check.LstIllegalMsg.Count > 0)
            {
                var item=syncInstrumentItem.LstSyncPramas.Where(s => s.TargetField == check.LstIllegalMsg[0].ColumnName).ToList<SyncParamasInfo>();
                if (item.Count == 1)
                {
                    MessageBox.Show(string.Format("数据不满足上传条件，请修改后再上传。错误数据:当前列名【{0}】,列值【{1}】", item[0].SourceField, check.LstIllegalMsg[0].ColumnValue));
                }
                else
                {
                    MessageBox.Show(string.Format("数据不满足上传条件，请修改后再上传。错误数据:CNAS列名【{0}】,列值【{1}】", check.LstIllegalMsg[0].ColumnName, check.LstIllegalMsg[0].ColumnValue));
                }
                return;
            }
            //逐行执行插入
            List<DataRow> lstError = new List<DataRow>();
            ProgressBarService.CreateBarForm("CNAS客户端上传", "上传数据...", dtTarget.Rows.Count, false, false, false);
            int SuccessCount = 0;
            foreach (DataRow dr in dtTarget.Rows)
            {
                dr.AcceptChanges();
                int iReturn = CnasDataOperationFact.CnasDataOperation().InsertDataToCNASTable(dr.Table, syncInstrumentItem);
                if (iReturn > 0)  //此时正常存储
                {
                    SuccessCount++;
                    ProgressBarService.UpdateProgress(SuccessCount);
                }
                else  //此时出现问题
                {
                    lstError.Add(dr);
                }
            }
            ProgressBarService.CloseBarForm();
            if (lstError.Count <= 0)
                MessageBox.Show("上传完成！");
            else
            {
                log.ErrorFormat("未成功上传的数据如下：{0}", ListToString(lstError));
                MessageBox.Show("上传过程中发生异常，存在部分数据未成功上传，请联系管理员！");
            }
        }

        private string TestConvertValueToTarget(DataRow drTarget, DataRow drSource, string strTargetColumn,string strSourceColumn)
        {
            string strErrorMsg = "";
            try
            {
                drTarget[strTargetColumn] = drSource[strSourceColumn];
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
                strErrorMsg = ex.Message;
            }
            return strErrorMsg;
        }

        private string ListToString(List<DataRow> lst)
        {
            return JsonConvert.SerializeObject(lst);
        }
        private List<DataRow> StringToList(string strList)
        {
            return JsonConvert.DeserializeObject<List<DataRow>>(strList);
        }

        private void cmbColumns_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbColumns.SelectedItem == null) return;
            KeyValuePair<string, Type> obj = (KeyValuePair<string, Type>)cmbColumns.SelectedItem;
            if (DictComboBox.ContainsKey(obj.Key))
            {
                Type selectType = DictComboBox[obj.Key];

                switch (selectType.ToString())
                {                   
                    case "System.DateTime":
                        UseDateTimeControl();
                        break;
                    case "System.Double":
                    case "System.Int64":
                    case "System.Int32":
                        UseNormalControl();
                        //绑定条件ComboBox
                        combCondition.DataSource = lstIntOrDouble ;
                        break;
                    case "System.Byte[]":
                    case "System.String":
                    default:
                        UseNormalControl();
                        //绑定条件ComboBox
                        combCondition.DataSource = lstText;
                        break;
                }
            }
        }

        /// <summary>
        /// 使用时间类型专用的查询控件组
        /// </summary>
        private void UseDateTimeControl()
        {
            if (pnlCheck.Controls.Contains(pnlText))
                pnlCheck.Controls.Remove(pnlText);
            if (!pnlCheck.Controls.Contains(pnlDate))
            {
                pnlCheck.Controls.Add(pnlDate);
                pnlDate.Visible = true;
                pnlDate.Dock = DockStyle.Fill;
            }
        }

        /// <summary>
        /// 使用标准的查询控件组
        /// </summary>
        private void UseNormalControl()
        {
            if (pnlCheck.Controls.Contains(pnlDate))
                pnlCheck.Controls.Remove(pnlDate);
            if (!pnlCheck.Controls.Contains(pnlText))
            {
                pnlCheck.Controls.Add(pnlText);
                pnlText.Visible = true;
                pnlText.Dock = DockStyle.Fill;
            }
        }

        /// <summary>
        /// 查询满足满足条件的项
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFind_Click(object sender, EventArgs e)
        {
            if (cmbColumns.SelectedValue == null) return;
            //1.合法性检测
            if (DictComboBox[cmbColumns.SelectedValue.ToString()].ToString().Equals("System.DateTime"))
            {
                if (dtpTarget.Value < dtpSource.Value)
                {
                    MessageBox.Show("查询时间需要一个有效的时间范围！");
                    return;
                }
            }
            else
            {
                if (this.txtFind.Text.Trim() == "")  //为空  认为是取消查询
                {
                    btnCancelFind_Click(sender, e);
                    return;
                }               
            }

            //2.将datagridview中满足条件的项修改背景色
            //2.1 判断当前显示的datagridview是否含有旧的查询数据
            //2.2 将满足条件的项背景色改为特殊颜色
            foreach (DataGridViewRow dgvrow in dgvSyncData.Rows)
            {
                dgvrow.DefaultCellStyle.BackColor = Color.White;

                //查询列的当前值
                string strGuid  = dgvrow.Cells["GridGuid"].Value.ToString();
                string strValue = dgvrow.Cells[cmbColumns.SelectedValue.ToString()].Value.ToString();

                //判断是否满足条件
                if (CheckMatchCondition(strValue))
                {
                    dgvrow.DefaultCellStyle.BackColor = FinedBackColor;
                }
            }
        }

        private bool CheckMatchCondition(string strValue)
        {
            if (DictComboBox[cmbColumns.SelectedValue.ToString()].ToString().Equals("System.DateTime"))
            {
                DateTime dt= DateTime.Now;
                if (!DateTime.TryParse(strValue, out dt)) return false;

                DateTime dtSource = dtpSource.Value;
                DateTime dtTarget = dtpTarget.Value;
                DateTime dtValue = dt;
                if (dt >= dtSource && dt <= dtTarget)
                    return true;
                else
                    return false;
            }
            else
            {
                string strFindText = this.txtFind.Text.ToString();
                bool bReturn = false;
                switch (combCondition.SelectedValue.ToString())
                {
                    case "等于":
                        bReturn=strValue == strFindText ? true : false;
                        break;
                    case "不等于":
                        bReturn = strValue != strFindText ?  true: false;
                        break;
                    case "包含":
                        bReturn = strValue.Contains(strFindText) ? true : false;
                        break;
                    case "不包含":
                        bReturn = !strValue.Contains(strFindText) ? true : false;
                        break;
                    case "大于":
                        bReturn = Convert.ToDouble(strValue)>Convert.ToDouble(strFindText) ? true : false;
                        break;
                    case "不小于":
                        bReturn = Convert.ToDouble(strValue) >= Convert.ToDouble(strFindText) ? true : false;
                        break;
                    case "小于":
                        bReturn = Convert.ToDouble(strValue) < Convert.ToDouble(strFindText) ? true : false;
                        break;
                    case "不大于":
                        bReturn = Convert.ToDouble(strValue) <= Convert.ToDouble(strFindText) ? true : false;
                        break;
                }
                return bReturn;
            }
        }


        /// <summary>
        /// 获得查询语句（非日期类型）
        /// </summary>
        /// <param name="strColumnName"></param>
        /// <param name="strColumnType"></param>
        /// <param name="strCondition"></param>
        /// <param name="strValue"></param>
        /// <returns></returns>
        private string GetSelectString(string strColumnName,string strCondition, string strValue)
        {
            string strCondi = "";
            switch (strCondition)
            {
                case "等于":
                    strCondi = "=";
                    break;
                case "不等于":
                    strCondi = "<>";
                    break;
                case "包含":
                    strCondi = "like";
                    break;
                case "不包含":
                    strCondi = "not like";
                    break;
                case "大于":
                    strCondi = ">";
                    break;
                case "不小于":
                    strCondi = ">=";
                    break;
                case "小于":
                    strCondi = "<";
                    break;
                case "不大于":
                    strCondi = "<=";
                    break;
            }
            if (strCondi == "like" || strCondi == "not like")
                return string.Format("{0} {1} '%{2}%'", strColumnName, strCondi, strValue);
            else
                return string.Format("{0} {1} '{2}'",strColumnName,strCondi,strValue);
        }


        private string GetDateSelectString(string strColumnName, DateTime dtSource, DateTime dtTarget)
        {
            string strSource = dtSource.ToString();
            string strTarget = dtTarget.ToString();

            return string.Format("{0}>='{1}' and {0}<='{2}'",strColumnName,strSource,strTarget) ;
        }

        private void btnConfig_Click(object sender, EventArgs e)
        {
            frmSyncParams frmSyncConfig = new frmSyncParams(syncInstrumentItem);
            frmSyncConfig.ParamsChangedDelegate = delegate (SyncInstrumentItemInfo instrumentItemInfo)
              {
                  syncInstrumentItem = instrumentItemInfo;

                  //重新绑定数据
                  dgvSyncData.DataSource = null;
                  dgvSyncData.Rows.Clear();
                  dgvSyncData.Columns.Clear();
                  combCondition.DataSource = null;
                  cmbColumns.DataSource = null;

                  BindData();
              };
            frmSyncConfig.ShowDialog();
        }

        private void btnCancelFind_Click(object sender, EventArgs e)
        {
            foreach (DataGridViewRow dgvrow in dgvSyncData.Rows)
            {
                if (dgvrow.DefaultCellStyle.BackColor != Color.White)
                    dgvrow.DefaultCellStyle.BackColor = Color.White;
            }
        }
    }
}
