/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Portions created by the Initial Developer are
 * Copyright (C) 2012 the Initial Developer.
 * All Rights Reserved.
 *
 * The Original Code is "http://semi-frame.googlecode.com/svn/trunk/".
 *
 * The Initial Developer of the Original Code is the author below.
 */

/**
 * @file EntityForm.cs
 * @brief auto generated.
 * @author mornongcloud
 * @date 2011/07/21
 */

using masterframe.control;
using masterframe.model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;

namespace masterframe.view
{
    /// <summary>
    /// entity control form 
    /// </summary>
    public partial class EntityForm : Form
    {
        MyEntity entity;

        private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

        /// <summary>
        /// entity control form constructor 
        /// </summary>
        public EntityForm()
        {
            InitializeComponent();

            this.buttonDisabled();

            try
            {
                entity = new MyEntity(MasterPool.settings.DataSource
                    , MasterPool.settings.SelectSql
                    , MasterPool.settings.DeleteSql);
            }
            catch (Exception ex)
            {
                this.textBox1.Text = "Unable to connect to the DB.";
                logger.Debug(this.textBox1.Text);
                button4.Enabled = true;
                //logger.Error(ex.Message, ex.InnerException == null ? ex : ex.InnerException);
                logger.Error(ex, ex.Message);
                return;
            }
            //sql_select = MasterPool.settings.SelectSql;

            this.textBox1.Text = this.reflesh();

            //sql_delete = MasterPool.settings.DeleteSql;
            //this.entity.keycnt = Entity.CountChar(sql_delete, '@');

            button4.Enabled = true;

            dataGridView1.RowHeadersWidth = 56;
            dataGridView1.AllowUserToDeleteRows = false;

            //So that can not be sorted
            if (!MasterPool.settings.Sort)
            {
                foreach (DataGridViewColumn c in dataGridView1.Columns)
                    c.SortMode = DataGridViewColumnSortMode.NotSortable;
            }

            //button3.Enabled = (0 == MasterPool.settings.DeleteLock);

            ////if (!bl) return;
            if (0 < dataGridView1.RowCount)
            {
                //foreach (MasterMaintenance.Validater.StValidate valid
                // in entity.validater.config.Values) 
                int wid = 91;
                //foreach (DataGridViewColumn c in dataGridView1.Columns)
                for (int i = 0; i < dataGridView1.Columns.Count; i++)
                {
                    var c = dataGridView1.Columns[i];
                    //SELECT_OPTION.config
                    //this.createSelectOption(valid.name, valid.type);
                    this.createSelectOption(c.Name, c.ValueType.Name);
                    //COLUMN.config
                    this.setColumnSettings(c.Name);

                    wid += c.Width;
                }
                this.Width = wid;
                this.textBox1.Width = wid - 20;
            }

            // delete
            if (0 < MasterPool.settings.DeleteLock)
            {
                int cnt = this.entity.keycnt;
                if (cnt < MasterPool.settings.DeleteLock) cnt = MasterPool.settings.DeleteLock;
                for (int i = 0; i < cnt && i < dataGridView1.Columns.Count; i++)
                {
                    dataGridView1.Columns[i].ReadOnly = true;
                    dataGridView1.Columns[i].DefaultCellStyle.BackColor = System.Drawing.Color.Silver;
                }
            }

            this.buttonEnabled();
        }

        /// <summary>
        /// Display SELECT OPTION
        /// </summary>
        /// <param name="colName"></param>
        /// <param name="typeNm"></param>
        private void createSelectOption(string colName, string typeNm)
        {
            Dictionary<string, List<string>> dic = masterframe.util.ConfigUtil.GetSettings(colName);
            if (0 == dic.Count) return;
            if (null == dataGridView1.Columns[colName]) return;

            //Create a DataGridViewComboBoxColumn
            DataGridViewComboBoxColumn column = new DataGridViewComboBoxColumn();
            //To create a list of items to be displayed in the ComboBox.
            //DataTable typeTable = new DataTable("Type");
            DataTable typeTable = new DataTable(colName);

            typeTable.Columns.Add("Display", typeof(string));

            typeNm = typeNm.ToLower();
            if (typeNm.Contains("int"))
            {
                typeTable.Columns.Add("Value", typeof(int));
                //typeTable.Rows.Add("", 0); // Figures without blank
                foreach (string ky in dic.Keys)
                {
                    if (0 < dic[ky].Count)
                    {
                        int ik;
                        if (null != dic[ky][0] && int.TryParse(ky, out ik))
                        {
                            //typeTable.Rows.Add(ky + ":" + dic[ky][0], ik);
                            typeTable.Rows.Add(dic[ky][0], ik);
                        }
                    }
                }
            }
            else
            {
                typeTable.Columns.Add("Value", typeof(string));
                typeTable.Rows.Add("", "");
                foreach (string ky in dic.Keys)
                {
                    if (0 < dic[ky].Count)
                    {
                        if (null != dic[ky][0])
                        {
                            //typeTable.Rows.Add(ky + ":" + dic[ky][0], ky);
                            typeTable.Rows.Add(dic[ky][0], ky);
                        }
                    }
                }
            }

            //The actual value is "Value" column , text display is the "Display" column.
            column.DisplayMember = "Display";
            column.ValueMember = "Value";
            //Set the name of the column to be displayed.
            //Set DataSource of DataGridViewComboBoxColumn
            column.DataSource = typeTable;
            column.FlatStyle = FlatStyle.Flat;
            //The name of the inserted column.
            //column.Name = "Type";
            column.Name = colName;

            //Set the name of the column to be displayed.
            //column.DataPropertyName = dataGridView1.Columns["Type"].DataPropertyName;
            column.DataPropertyName = dataGridView1.Columns[colName].DataPropertyName;
            //Inserted into a position where the current column is present
            //int idx = dataGridView1.Columns["Type"].Index;
            int idx = dataGridView1.Columns[colName].Index;
            dataGridView1.Columns.Insert(idx, column);
            //Delete the column at current.
            dataGridView1.Columns.RemoveAt(idx + 1);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="colName"></param>
        /// <param name="typeNm"></param>
        private void setColumnSettings(string colName)
        {

            if (0 == this.entity.columnsetting.config.Count) return;
            if (null == dataGridView1.Columns[colName]) return;
            if (!this.entity.columnsetting.config.ContainsKey(colName)) return;

            var stt = this.entity.columnsetting.config[colName];

            if (null != stt.name && 0 < stt.name.Length)
                dataGridView1.Columns[colName].HeaderText = stt.name;

            dataGridView1.Columns[colName].Width = stt.width;

            // 2017.11
            if (0 == stt.width)
                dataGridView1.Columns[colName].Visible = false;

            if (null != stt.format && 0 < stt.format.Length)
                dataGridView1.Columns[colName].DefaultCellStyle.Format = stt.format;
        }

        //Data display
        private string reflesh()
        {
            changecell.Clear();

            //string ret = entity.Load(sql_select);
            string ret = entity.Load();
            //if (0 < ret.Length)
            //    ret = "[MASTER] " + ret;
            //this.textBox1.Text = ret;
            this.dataGridView1.DataSource = entity.entities;

            if (0 < ret.Length)
            {
                button2.Enabled = false;
                button3.Enabled = false;
                //return false;
                return ret;
            }

            ////SLAVE DB
            //if (null != this.rpl)
            //{
            //    ret = this.rpl.Load();
            //    if (0 < ret.Length)
            //        ret = "[SLAVE] " + ret;
            //    //this.textBox1.Text = ret;
            //    //if (0 < ret.Length)
            //    //    return false;
            //}
            //else if (0 < MasterPool.settings.ReplDataSource.Length)
            //{
            //    //this.textBox1.Text = "Backup DB is not running.";
            //    //button2.Enabled = false;
            //    //button3.Enabled = false;
            //}
            ////return 0 == ret.Length;

            Application.DoEvents();

            return ret;
        }

        // Reflesh
        private void button1_Click(object sender, EventArgs e)
        {
            logger.Debug("Reflesh button presses.");

            if (!button1.Enabled) return;

            this.buttonDisabled();
            this.textBox1.Text = this.reflesh();

            if (0 == this.textBox1.Text.Length) this.textBox1.Text = "Display data was refreshed.";
            logger.Info(this.textBox1.Text);

            this.buttonEnabled();
        }

        // Registration
        private void button2_Click(object sender, EventArgs e)
        {
            logger.Debug("Registration button presses");

            this.textBox1.Text = "";

            if (!button2.Enabled) return;

            this.buttonDisabled();

            bool bl = this.update();

            if (bl) this.reflesh();

            if (0 == this.textBox1.Text.Length) this.textBox1.Text = "It has registered the data.";
            logger.Info(this.textBox1.Text);

            this.buttonEnabled();
        }

        // Registration
        private bool update()
        {
            string ret = entity.Validate();
            if (0 == ret.Length)
            {
                ret = entity.InsertOrUpdate();
            }
            this.textBox1.Text = ret;

            if (0 < ret.Length)
            {
                return false;
            }

            this.textBox1.Text = ret;

            return (0 == ret.Length);
        }

        // Delete
        private void button3_Click(object sender, EventArgs e)
        {
            logger.Debug("Delete button presses");

            if (!button3.Enabled) return;
            this.buttonDisabled();

            this.textBox1.Text = "";

            var delrowidx = new List<int>();
            //var delkys = new List<int>();
            var delrows = new List<DataGridViewRow>();
            try
            {
                foreach (DataGridViewRow item in this.dataGridView1.SelectedRows)
                {
                    delrowidx.Add(item.Index);
                }
                delrowidx.Sort();
                delrowidx.Reverse();

                foreach (DataGridViewRow item in this.dataGridView1.SelectedRows)
                {
                    //int ky = 0;
                    //if (null != item.Cells[0].Value 
                    //    && int.TryParse(item.Cells[0].Value.ToString(), out ky))
                    //    delkys.Add(ky);
                    delrows.Add(item);
                }

                string ret = "";
                //ret = entity.DeleteByKey(sql_delete, delrows);
                ret = entity.DeleteByKey(delrows);
                if (0 < ret.Length)
                {
                    //ret = "[MASTER] " + ret;
                    this.textBox1.Text = ret;
                    this.buttonEnabled();
                    return;
                }

                foreach (int idx in delrowidx)
                {
                    if (!this.dataGridView1.Rows[idx].IsNewRow)
                    {
                        this.dataGridView1.Rows.RemoveAt(idx);
                    }
                }
                Application.DoEvents();
            }
            catch (Exception ex)
            {
                this.textBox1.Text = "The change of the data has failed [" + ex.Message + "]";
                logger.Error(ex, ex.Message);
            }

            if (0 < delrowidx.Count && 0 == this.textBox1.Text.Length) this.textBox1.Text = "It was deleted data.";
            if (0 == delrowidx.Count && 0 == this.textBox1.Text.Length) this.textBox1.Text = "Select the line number , please pless the Delete buttun.";

            logger.Info(this.textBox1.Text);

            this.buttonEnabled();
        }

        // Exit
        private void button4_Click(object sender, EventArgs e)
        {
            logger.Debug("Exit buttun presses");

            if (!button4.Enabled) return;

            this.buttonDisabled();

            Close();

            this.buttonEnabled();
        }


        private void buttonEnabled()
        {
            Application.DoEvents();

            button1.Enabled = true;
            button2.Enabled = (MasterPool.settings.Update);
            button3.Enabled = (0 == MasterPool.settings.DeleteLock);
            button4.Enabled = true;
            this.onevent = true;
            this.dataGridView1.Enabled = true;
            this.onevent = false;
        }

        private void buttonDisabled()
        {
            this.onevent = true;
            this.dataGridView1.Enabled = false;
            this.onevent = false;
            button1.Enabled = false;
            button2.Enabled = false;
            button3.Enabled = false;
            button4.Enabled = false;
        }

        bool onevent = false;

        //List<DataGridViewCell> changecell = new List<DataGridViewCell>();
        Dictionary<int, List<int>> changecell = new Dictionary<int, List<int>>();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                if (e.ColumnIndex >= 0 && e.RowIndex >= 0)  //not header
                {
                    DataGridView dgv = (DataGridView)sender;
                    dgv[e.ColumnIndex, e.RowIndex].Style.ForeColor = System.Drawing.Color.Red;

                    ////Digit display correction
                    //if (2 == e.ColumnIndex)
                    //{
                    //    var vl = dgv[e.ColumnIndex, e.RowIndex].Value;
                    //    if (System.Text.Encoding.ASCII.GetByteCount(vl.ToString()) < 4)
                    //    {
                    //        vl = vl.ToString().PadLeft(4, '0');
                    //        dgv[e.ColumnIndex, e.RowIndex].Value = vl;
                    //    }
                    //}

                    if (MasterPool.settings.Sort) //Sort correspondence
                    {
                        int ky = int.Parse(dgv[0, e.RowIndex].Value.ToString());
                        if (!changecell.ContainsKey(ky))
                            changecell.Add(ky, new List<int>());
                        changecell[ky].Add(e.ColumnIndex);
                    }
                }
            }
            catch (Exception ex)
            {
                //logger.Error(ex.Message, ex.InnerException == null ? ex : ex.InnerException);
                logger.Error(ex, ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            if (onevent) return;
            this.onevent = true;

            try
            {
                DataGridView dgv = (DataGridView)sender;

                //Serial number
                if (dgv.Rows[e.RowIndex].HeaderCell.Value == null
                    || int.Parse(dgv.Rows[e.RowIndex].HeaderCell.Value.ToString()) != (e.RowIndex + 1))
                    dgv.Rows[e.RowIndex].HeaderCell.Value = (e.RowIndex + 1).ToString("000");

                if (MasterPool.settings.Sort) //ソート対応
                {
                    System.Drawing.Color[] cols = new System.Drawing.Color[10];

                    //pre-edit=black
                    int idx = 0;
                    foreach (DataGridViewCell cl in dgv.Rows[e.RowIndex].Cells)
                    {
                        cols[idx] = System.Drawing.Color.Black;
                        idx++;
                    }
                    //n the editing=red
                    if (null != dgv[0, e.RowIndex].Value)
                    {
                        int ky = 0;
                        if (int.TryParse(dgv.Rows[e.RowIndex].Cells[0].Value.ToString(), out ky))
                        {
                            if (changecell.ContainsKey(ky))
                            {
                                foreach (int cl in changecell[ky])
                                    cols[cl] = System.Drawing.Color.Red;
                            }
                        }
                    }
                    //So as not to generate an event as much as possible
                    idx = 0;
                    foreach (DataGridViewCell cl in dgv.Rows[e.RowIndex].Cells)
                    {
                        if ((cl.Style.ForeColor == System.Drawing.Color.Red && cols[idx] == System.Drawing.Color.Black)
                            || (cl.Style.ForeColor != System.Drawing.Color.Red && cols[idx] == System.Drawing.Color.Red))
                        {
                            cl.Style.ForeColor = cols[idx];
                            Application.DoEvents(); //Escape RowPostPaint events
                        }
                        idx++;
                    }
                }

            }
            catch (Exception ex)
            {
                //logger.Error(ex.Message, ex.InnerException == null ? ex : ex.InnerException);
                logger.Error(ex, ex.Message);
            }
            //Application.DoEvents();
            this.onevent = false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            try
            {
                if (0 == e.ColumnIndex)
                {
                    DataGridView dgv = (DataGridView)sender;
                    dgv[e.ColumnIndex, e.RowIndex].Style.ForeColor = System.Drawing.Color.Red;
                    this.textBox1.Text = "I was not able to enter because of bad records (Row:" + (e.RowIndex + 1).ToString() + "-th) ";
                    logger.Info(this.textBox1.Text);
                }
            }
            catch (Exception ex)
            {
                //logger.Error(ex.Message, ex.InnerException == null ? ex : ex.InnerException);
                logger.Error(ex, ex.Message);
            }
            e.Cancel = false;
        }
    }
}
