using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ProjectManagementSystem.UI
{
    public partial class DataGridUI : UserControl, IDisplayUI
    {
        private bool needResize = true;
        private BindingSource bindingSource = new BindingSource();

        public DataGridUI()
        {
            InitializeComponent();
            DoubleBufferedDataGirdView(dataGridView1, true);

            dataGridView1.SelectionChanged += (s, e) =>
            {
                dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
            };

            this.dataGridView1.DataSource = bindingSource;
        }

        private void DoubleBufferedDataGirdView(DataGridView dgv, bool flag)
        {
            Type dgvType = dgv.GetType();
            PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
            pi.SetValue(dgv, flag, null);
        }


        public virtual bool Init()
        {
            return true;
        }

        public virtual void UpdateDisplay()
        {
        }

        public DataTable GetDataTable()
        {
            DataTable dt = new DataTable();
            for (int count = 0; count < dataGridView1.Columns.Count; count++)
            {
                if (dataGridView1.Columns[count].Visible)
                {
                    DataColumn dc = new DataColumn(dataGridView1.Columns[count].HeaderText.ToString());
                    dt.Columns.Add(dc);
                }
            }


            for (int count = 0; count < dataGridView1.Rows.Count; count++)
            {
                DataRow dr = dt.NewRow();

                int colCount = 0;
                for (int countsub = 0; countsub < dataGridView1.Columns.Count; countsub++)
                {
                    if (dataGridView1.Columns[countsub].Visible)
                    {
                        dr[colCount] = dataGridView1.Rows[count].Cells[countsub].Value.ToString();
                        colCount++;
                    }
                }
                dt.Rows.Add(dr);
            }

            return dt;
        }

        public string GetCurrentColValue(string colName)
        {
            if (dataGridView1.CurrentRow == null)
            {
                return null;
            }

            if (!dataGridView1.Columns.Contains(colName))
            {
                return null;
            }

            int DGVCurrentRow = dataGridView1.CurrentRow.Index;


            if (DGVCurrentRow < 0 || dataGridView1.Rows[DGVCurrentRow].Cells[colName].Value == null)
            {
                return null;
            }

            string strOrderID = dataGridView1.Rows[DGVCurrentRow].Cells[colName].Value.ToString();
            return strOrderID;
        }


        private void UpdateBindingSource<T>(IEnumerable<T> dataList)
        {
            //clear
            var dataListCount = dataList?.Count() ?? 0;
            if (dataListCount == 0)
            {
                if (bindingSource.Count > 0)
                {
                    bindingSource.Clear();
                }
                return;
            }

            //fully add
            if (bindingSource.Count == 0)
            {
                foreach (var s in dataList)
                {
                    bindingSource.Add(s);
                }
                needResize = true;
                return;
            }

            //remove
            if (dataListCount < bindingSource.Count)
            {
                var removeCount = bindingSource.Count - dataListCount;
                var lastIndex = bindingSource.Count - 1;

                for (int idx = 0; idx < removeCount; idx++)
                {
                    var index = lastIndex - idx;
                    bindingSource.RemoveAt(index);
                }
                needResize = true;
            }

            //add or update
            int i = 0;
            foreach (var s in dataList)
            {
                if (bindingSource.Count > i)
                {
                    bindingSource[i] = s;
                }
                else
                {
                    bindingSource.Add(s);
                    needResize = true;
                }
                i++;
            }
        }

        public void ShowDataGrid<T>(IEnumerable<T> dataSource, bool directly = false)
        {
            this.Invoke(new MethodInvoker(() =>
            {
                this.SuspendLayout();

                if (directly)
                {
                    bindingSource.DataSource = dataSource;
                }
                else
                {
                    UpdateBindingSource(dataSource);
                }

                foreach (DataGridViewColumn column in dataGridView1.Columns)
                {
                    if (column.Name.Contains("Time"))
                    {
                        column.DefaultCellStyle.Format = "G";
                    }
                    if (column.Name.Contains("HEX"))
                    {
                        column.DefaultCellStyle.Format = "X2";
                    }
                }

                var keyInfo = Common.Config.ExcelConfig.Instance.ColumnKeyInfoDict;
                foreach (DataGridViewColumn column in dataGridView1.Columns)
                {
                    if (keyInfo.TryGetValue(column.Name, out var columnKeyInfo))
                    {
                        column.HeaderText = columnKeyInfo.HeaderText;
                        column.Visible = columnKeyInfo.Visible;

                        if (!string.IsNullOrEmpty(columnKeyInfo.Format))
                        {
                            column.DefaultCellStyle.Format = columnKeyInfo.Format;
                        }
                    }
                    else
                    {
                        var displayName = typeof(T)?.GetProperty(column.Name)?.GetCustomAttribute<DisplayNameAttribute>()?.DisplayName;

                        if (!string.IsNullOrEmpty(displayName))
                        {
                            column.HeaderText = displayName;
                        }
                        //else
                        //{
                        //    column.Visible = false;
                        //}
                    }
                }


                if (needResize && bindingSource.Count > 0)
                {
                    needResize = false;
                    dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
                }

                this.ResumeLayout(false);
            }));

        }


    }
}
