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

namespace SeSue.FormClasses.Dgv
{
    public partial class Dgv : UserControl
    {
        private List<DgvColumn> dgvCols;
        private DataTable dt;
        private Control container;

        public Dgv(Control container, List<DgvColumn> dgvCols,
            Color backColor, Color gridColor,
            bool colHeadersVisible, bool rowHeadersVisible,
            int rowHeight, int headerVerticalPadding,
            bool allowAddRows, bool allowDeleteRows, bool allowOrderCols, bool allowResizeCols, bool allowResizeRows, bool allowMultiSelect,
            DataGridViewClipboardCopyMode copyMode, DataGridViewSelectionMode selectionMode, ScrollBars scrollBars, DockStyle dockStyle)
        {
            InitializeComponent();
            this.container = container;
            this.dgvCols = dgvCols;
            this.dataGridView.BackgroundColor = backColor;
            this.dataGridView.GridColor = gridColor;
            this.dataGridView.ColumnHeadersVisible = colHeadersVisible;
            this.dataGridView.RowHeadersVisible = rowHeadersVisible;
            this.dataGridView.RowTemplate.Height = rowHeight;
            this.dataGridView.AllowUserToAddRows = allowAddRows;
            this.dataGridView.AllowUserToDeleteRows = allowDeleteRows;
            this.dataGridView.AllowUserToOrderColumns = allowOrderCols;
            this.dataGridView.AllowUserToResizeColumns = allowResizeCols;
            this.dataGridView.AllowUserToResizeRows = allowResizeRows;
            this.dataGridView.MultiSelect = allowMultiSelect;
            this.dataGridView.ClipboardCopyMode = copyMode;
            this.dataGridView.SelectionMode = selectionMode;
            this.dataGridView.ScrollBars = scrollBars;
            this.dataGridView.Dock = dockStyle;
            this.Dock = DockStyle.Fill;
            this.dataGridView.DataSource = getEmptyDatatable();
            initializeDgvColsFormats(headerVerticalPadding);

            //this.dataGridView.Columns[0].DefaultCellStyle.BackColor = Color.Red;
            this.dataGridView.Columns[0].HeaderCell.Style.BackColor = Color.Red;

            /*
            this.dataGridView.EnableHeadersVisualStyles = false;
            this.dataGridView.ColumnHeadersDefaultCellStyle.BackColor = Color.DarkSlateGray;
            this.dataGridView.ColumnHeadersDefaultCellStyle.ForeColor = Color.White;
            this.dataGridView.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.None;//*/
            
            
        }

        public DataTable getEmptyDatatable()
        {
            this.dt = new DataTable();
            for (int i = 0; i < dgvCols.Count; i++) { dt.Columns.Add(dgvCols[i].getHeader()); }
            for (int i = 0; i < dgvCols.Count; i++) { if (dgvCols[i].getDataType() != null) { dt.Columns[i].DataType = dgvCols[i].getDataType(); } }
            return dt;
        }

        // PUBLIC
        public void remove() { this.container.Controls.Remove(this); }
        public void setDataTable(DataTable dataTable) { this.dataGridView.DataSource = dataTable; }
        public void initializeDgvColsFormats(int headerVerticalPadding)
        {
            for (int i = 0; i < dgvCols.Count; i++) { this.dataGridView.Columns[i].Visible = dgvCols[i].getVisible(); }
            for (int i = 0; i < dgvCols.Count; i++)
            {
                dgvCols[i].initializeFormat(this.dataGridView.Columns[i], headerVerticalPadding);
            }
            this.dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
            for (int i = 0; i < dgvCols.Count; i++)
            {
                double w = dgvCols[i].getWidthPerc(); if (w == 0) { w = 0.001; }
                this.dataGridView.Columns[i].FillWeight = Convert.ToInt16(w * 1000);
            }
        }
        public void onResize()
        {
            //for (int i = 0; i < dgvCols.Count; i++) { this.dataGridView.Columns[i].Visible = dgvCols[i].getVisible(); }
            /*
            int totalW = this.dataGridView.Width;
            if (this.dt.Rows.Count > 20) { totalW = totalW - 20; }
            int sum = 0;
            for (int i = 0; i < dgvCols.Count - 1; i++)
            {
                int wCol = Convert.ToInt16(Math.Round(totalW * dgvCols[i].getWidthPerc()));
                sum += wCol;
                this.dataGridView.Columns[i].Width = wCol;
            }
            this.dataGridView.Columns[dgvCols.Count - 1].Width = totalW - sum - 1;//*/
        }
        public List<string> getDtAsLines()
        {
            if (this.dgvCols == null) { return new List<string>(); }
            if (this.dgvCols.Count == 0) { return new List<string>(); }
            List<string> lines = new List<string>();
            string line = this.dgvCols[0].getHeader();
            for (int j = 1; j < this.dgvCols.Count; j++) { line = line + '\t' + this.dgvCols[j].getHeader(); }
            lines.Add(line);
            for (int i = 0; i < this.dt.Rows.Count; i++)
            {
                line = this.dt.Rows[i][0].ToString();
                for (int j = 1; j < this.dgvCols.Count; j++) { line = line + '\t' + this.dt.Rows[i][j].ToString(); }
                lines.Add(line);
            }
            return lines;
        }

        // DATA OPERATIONS
        public void clearRows() { this.dt.Rows.Clear(); }
        public void addRow(List<string> values)
        {
            DataRow dr = this.dt.NewRow();
            for (int i = 0; i < values.Count; i++) { dr[i] = values[i]; }
            dt.Rows.Add(dr);
        }
        public void addRows(List<List<string>> rows) { foreach (List<string> values in rows) { addRow(values); } }


        // RESIZE
        private void dataGridView_Resize(object sender, EventArgs e) { onResize(); }


        // GETTERS
        public DataGridView getDataGridView() { return this.dataGridView; }
        public DataTable getDataTable() { return this.dt; }
        public string getDtValue(int row, int col) { return this.dt.Rows[row][col].ToString(); }
        public int getDtValueInt(int row, int col) { return Convert.ToInt16(getDtValue(row, col)); }
        public double getDtValueDbl(int row, int col) { return Convert.ToDouble(getDtValue(row, col)); }
        public bool getDtValueBool(int row, int col) { return Convert.ToBoolean(getDtValue(row, col)); }
        public string getCellValue(int row, int col) { return this.dataGridView.Rows[row].Cells[col].Value.ToString(); }
        public double getCellValueDbl(int row, int col) { return Convert.ToDouble(getCellValue(row, col)); }
        public int getCellValueInt(int row, int col) { return Convert.ToInt32(getCellValue(row, col)); }
        public bool getCellValueBool(int row, int col) { return Convert.ToBoolean(getCellValue(row, col)); }
        public int getRowIndex(int col, string val) { for (int i = 0; i < this.dataGridView.Rows.Count; i++) { if (getCellValue(i, col) == val) { return i; } } return -1; }
        public int getDtIndex(int col, string val) { for (int i = 0; i < this.dt.Rows.Count; i++) { if (dt.Rows[i][col].ToString() == val) { return i; } } return -1; }


        // SETTERS
        public void setDtValue(int row, int col, string val) { this.dt.Rows[row][col] = val; }
        public void setCellValue(int row, int col, string val) { this.dataGridView.Rows[row].Cells[col].Value = val; }
        public void setCellValue(int row, int col, double val) { this.dataGridView.Rows[row].Cells[col].Value = val; }
        public void setCellValue(int row, int col, int val) { this.dataGridView.Rows[row].Cells[col].Value = val; }
        public void setCellBackColor(int row, int col, Color color) { this.dataGridView.Rows[row].Cells[col].Style.BackColor = color; }
        public void setCellForeColor(int row, int col, Color color) { this.dataGridView.Rows[row].Cells[col].Style.ForeColor = color; }
        public void setCellReadOnly(int row, int col, bool readOnly) { this.dataGridView.Rows[row].Cells[col].ReadOnly = readOnly; }

        public void setColBackColor(int col, Color color) { this.dataGridView.Columns[col].DefaultCellStyle.BackColor = color; }
        public void setColForeColor(int col, Color color) { this.dataGridView.Columns[col].DefaultCellStyle.ForeColor = color; }
        public void setColReadOnly(int col, bool readOnly) { this.dataGridView.Columns[col].ReadOnly = readOnly; }


        // HOT KEYS
        private void dataGridView_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.A) // SELECT ALL
            {
                this.dataGridView.SelectAll();
            }
                /*
            else if (false && e.Control && e.KeyCode == Keys.V) // PASTE
            {
                string s = Clipboard.GetText();
                string[] lines = s.Split('\n');
                int iFail = 0, iRow = dataGridView.CurrentCell.RowIndex;
                int iCol = dataGridView.CurrentCell.ColumnIndex;
                DataGridViewCell oCell;
                foreach (string line in lines)
                {
                    if (iRow < dataGridView.RowCount && line.Length > 0)
                    {
                        string[] sCells = line.Split('\t');
                        for (int i = 0; i < sCells.GetLength(0); ++i)
                        {
                            sCells[i] = Str.trim(sCells[i]);////////////////
                            if (iCol + i < this.dataGridView.ColumnCount)
                            {
                                oCell = dataGridView[iCol + i, iRow];
                                if (!oCell.ReadOnly)
                                {
                                    if (oCell.Value.ToString() != sCells[i])
                                    {
                                        //oCell.Value = Convert.ChangeType(sCells[i], oCell.ValueType);
                                        //oCell.Style.BackColor = Color.Tomato;
                                        oCell.Value = sCells[i];
                                    }
                                }
                            }
                            else
                            { break; }
                        }
                        iRow++;
                    }
                    else
                    { break; }
                    if (iFail > 0)
                        MessageBox.Show(string.Format("{0} updates failed due" +
                                        " to read only column setting", iFail));
                }

                //this.dataGridView.SelectAll();
            }//*/
        }

    }
}
