/// <summary>
/// データファイル読込画面
/// </summary>
/// <create>2010/01/26</create>
/// <modifier></modifier>
/// <modify></modify>
/// <modification></modification>
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using Microsoft.VisualBasic.FileIO;

namespace lsor
{
    /// <summary><para>class outline:</para>
    /// <para>データファイル読込画面出力制御クラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[ver 1.0.0][2010/02/02][新規作成]</para>
    /// </remarks>
    public partial class DataFileOpen : Form
    {
        #region プライベート変数

        /// <summary>プロジェクト共通データ</summary>
        private CommonData _commonData = new CommonData();
        /// <summary>文字エンコーディング</summary>
        private Encoding _enc = Encoding.Default;

        #endregion

        #region コンストラクタ

        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>DataFileOpen csDataFileOpen = new DataFileOpen(commonData)</para>
        /// </example>
        /// <param name="commonData">共通データ</param>
        /// <returns>データファイル読込画面出力制御クラス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public DataFileOpen(CommonData commonData)
        {
            this._commonData = commonData;

            InitializeComponent();
        }

        #endregion

        #region イベントハンドラ

        #region フォーム_Load

        /// <summary><para>method outline:</para>
        /// <para>フォームロード時の処理</para>
        /// </summary>
        /// <param name="sender">発生元オブジェクト</param>
        /// <param name="e">イベントの追加情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void DataFileOpen_Load(object sender, EventArgs e)
        {

            Color bgColor = dgvFileList.ColumnHeadersDefaultCellStyle.BackColor;
            dgvFileList.Columns[0].DefaultCellStyle.BackColor = bgColor;
            dgvFileList.Columns[1].DefaultCellStyle.BackColor = bgColor;

            DataGridViewButtonColumn column1 = new DataGridViewButtonColumn();
            column1.UseColumnTextForButtonValue = true;
            column1.DefaultCellStyle.BackColor = this.cmdCancel.BackColor;
            column1.Width = 50;
            column1.Name = Properties.HySAddinLsor2VieweEXEResources.BROWSE;  // 参照
            column1.Text = Properties.HySAddinLsor2VieweEXEResources.BROWSE;  // 参照
            dgvFileList.Columns.Add(column1);

            DataGridViewButtonColumn column2 = new DataGridViewButtonColumn();
            column2.UseColumnTextForButtonValue = true;
            column2.DefaultCellStyle.BackColor = this.cmdCancel.BackColor;
            column2.Width = 50;
            column2.Name = Properties.HySAddinLsor2VieweEXEResources.REMOVE;  // 消去
            column2.Text = Properties.HySAddinLsor2VieweEXEResources.REMOVE;  // 消去
            dgvFileList.Columns.Add(column2);

            dgvFileList.Rows.Add(Properties.HySAddinLsor2VieweEXEResources.CALCULATION_INPUT);   // 計算入力
            for (int row = 1; row <= 50; row++)
            {
                dgvFileList.Rows.Add(string.Format(Properties.HySAddinLsor2VieweEXEResources.CALCULATION_RESULT, row.ToString()));  // 計算結果
            }

            if (this._commonData.FileList.Count > 0)
            {
                for (int row = 0; row <= 50; row++)
                {
                    if (this._commonData.FileList[row].FileNm != null)
                    {
                        dgvFileList[1, row].Value = this._commonData.FileList[row].FileNm.ToString();
                        dgvFileList[1, row].Style.BackColor = Color.White;
                    }
                }
            }

            // メッセージ:読み込むデータファイルを指定してください。
            lblMessage.Text = Properties.HySAddinLsor2VieweEXEResources.MSG_INFO_SPECIFY_DATA_FILE_TO_LOAD;
            lblMessage.ForeColor = Color.Black;

            this.Height = 400;
        }

        #endregion

        #region 「参照／消去」ボタン_Click

        /// <summary><para>method outline:</para>
        /// <para>「参照／消去」ボタンクリック時の処理</para>
        /// </summary>
        /// <param name="sender">発生元オブジェクト</param>
        /// <param name="e">イベントの追加情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void dgvFileList_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (dgvFileList.Columns[e.ColumnIndex].Name == Properties.HySAddinLsor2VieweEXEResources.BROWSE)  // 参照
            {

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    dgvFileList[1, e.RowIndex].Value = openFileDialog.FileName;
                    dgvFileList[1, e.RowIndex].Style.BackColor = Color.White;
                }
                openFileDialog.Dispose();
            }
            else if (dgvFileList.Columns[e.ColumnIndex].Name == Properties.HySAddinLsor2VieweEXEResources.REMOVE) // 消去
            {
                Color bgColor = dgvFileList.ColumnHeadersDefaultCellStyle.BackColor;
                dgvFileList[1, e.RowIndex].Value = "";
                dgvFileList[1, e.RowIndex].Style.BackColor = bgColor;
            }
        }

        #endregion

        #region 「開く」ボタン_Click

        /// <summary><para>method outline:</para>
        /// <para>「開く」ボタンクリック時の処理</para>
        /// </summary>
        /// <param name="sender">発生元オブジェクト</param>
        /// <param name="e">イベントの追加情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void cmdOpen_Click(object sender, EventArgs e)
        {
            // FormClosingで処理
            this.Close();
        }

        #endregion

        #region 「取消」ボタン_Click

        /// <summary><para>method outline:</para>
        /// <para>「取消」ボタンクリック時の処理</para>
        /// </summary>
        /// <param name="sender">発生元オブジェクト</param>
        /// <param name="e">イベントの追加情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void cmdCancel_Click(object sender, EventArgs e)
        {
            // FormClosingで処理
            this.Close();
        }

        #endregion

        #region ファイル一覧_CellEndEdit

        /// <summary><para>method outline:</para>
        /// <para>ファイル一覧の選択セルに対して編集が終了した時の処理</para>
        /// </summary>
        /// <param name="sender">発生元オブジェクト</param>
        /// <param name="e">イベントの追加情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void dgvFileList_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (dgvFileList.CurrentCell.Value != null && dgvFileList.CurrentCell.Value.ToString() != "")
            {
                dgvFileList.CurrentCell.Style.BackColor = Color.White;
            }
        }

        #endregion

        #region フォーム_FormClosing

        /// <summary><para>method outline:</para>
        /// <para>フォームが閉じる時の処理</para>
        /// </summary>
        /// <param name="sender">発生元オブジェクト</param>
        /// <param name="e">イベントの追加情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void DataFileOpen_FormClosing(object sender, FormClosingEventArgs e)
        {
            // 結果入力ファイルのキー項目検索用
            ArrayList keyList = new ArrayList();

            if (this.DialogResult == DialogResult.OK)
            {

                // 未保存のデータファイルが無いか検索
                bool unsaveFlg = false;
                for (int i = 0; i < this._commonData.FileList.Count; i++)
                {
                    if (this._commonData.FileList[i].UnsaveFlg == true)
                    {
                        unsaveFlg = true;
                    }
                }
                if (unsaveFlg)
                {
                    DialogResult result;
                    // メッセージ:保存していないデータは破棄されます。よろしいですか？
                    result = MessageBox.Show(Properties.HySAddinLsor2VieweEXEResources.MSG_WARNING_UNSAVED_DATA_DISCARDED,
                        Properties.HySAddinLsor2VieweEXEResources.CAPTION_OPEN_DATA_FILE,
                            MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);
                    if (result != DialogResult.OK)
                    {
                        e.Cancel = true;
                        return;     // 処理中断
                    }
                }

                // ファイルオープンエラー発生フラグ
                Boolean bOpenError = false;

                // ファイル存在チェック
                for (int row = 0; row < dgvFileList.RowCount; row++)
                {
                    Color bgColor = dgvFileList.ColumnHeadersDefaultCellStyle.BackColor;
                    if (dgvFileList[1, row].Value != null && dgvFileList[1, row].Value.ToString() != "")
                    {
                        String path = dgvFileList[1, row].Value.ToString();
                        if (path.Length > 0)
                        {
                            if (System.IO.File.Exists(path) == false)
                            {
                                bOpenError = true;   // ファイルが見つからない
                                bgColor = Color.Pink;
                            }
                            else
                            {
                                bgColor = Color.White;
                            }
                        }
                    }
                    else
                    {
                        if (row == 0)
                        {
                            dgvFileList[1, row].Style.BackColor = Color.Pink;
                            // メッセージ:計算入力ファイルが指定されていません。
                            lblMessage.Text = Properties.HySAddinLsor2VieweEXEResources.MSG_ERROR_NOT_SPECIFIED_CALCULATION_INPUT_FILE;
                            lblMessage.ForeColor = Color.Red;
                            e.Cancel = true;        // 計算入力ファイルが指定されていない
                            return;     // 処理中断
                        }
                    }
                    dgvFileList[1, row].Style.BackColor = bgColor;
                }

                // ファイルオープンエラーチェック
                if (bOpenError)
                {
                    // メッセージ:オープンできないファイルが1つ以上あります。
                    lblMessage.Text = Properties.HySAddinLsor2VieweEXEResources.MSG_ERROR_ONE_OR_MORE_FILES_NOT_OPENED;
                    lblMessage.ForeColor = Color.Red;
                    e.Cancel = true;
                    return;     // 処理中断
                }

                List<InputFile> inputFilelist = new List<InputFile>();
                bool errFlg = false;

                // データファイルの読み込み
                InputFile inputFile;
                for (int row = 0; row < dgvFileList.RowCount; row++)
                {
                    inputFile = new InputFile();

                    inputFile.FileId = dgvFileList[0, row].Value.ToString();
                    if (dgvFileList[1, row].Value != null && dgvFileList[1, row].Value.ToString() != "")
                    {
                        inputFile.FileNm = dgvFileList[1, row].Value.ToString();
                        inputFile.UnsaveFlg = false;
                        inputFile.NewFileNm = "";
                        try
                        {

                            // CSV読込み
                            TextFieldParser parser = new TextFieldParser(inputFile.FileNm, this._enc);

                            using (parser)
                            {
                                parser.TextFieldType = FieldType.Delimited;
                                parser.SetDelimiters(",");

                                int rowCnt = 0;
                                int lineCnt = 0;

                                ArrayList csvData = new ArrayList();

                                List<ColumnData> columnList = new List<ColumnData>();
                                int columnCnt = 0;
                                ColumnData columnData = new ColumnData();

                                while (!parser.EndOfData)
                                {
                                    string[] csvRow = parser.ReadFields();  // 1行リード
                                    lineCnt++;

                                    if (csvRow[0].IndexOf("[start]") >= 0 || csvRow[0].IndexOf("[end]") >= 0)
                                    {
                                        continue;
                                    }
                                    if (csvRow[csvRow.Length - 1] == "")
                                    {   // 配列要素の最後が""の場合、行末に余分なカンマが入っていた可能性があるので削除
                                        // (余分なカンマが原因でヘッダ項目数<データカラム数になっている場合に、カラム数チェックでエラーにしない為)
                                        // 余分なカンマが原因でなかった場合も、データが空欄ということなので影響は無い
                                        Array.Resize(ref csvRow, csvRow.Length - 1);
                                    }

                                    if (rowCnt == 0)
                                    {
                                        // 項目名の格納
                                        int i = 0;
                                        foreach (string field in csvRow)
                                        {
                                            columnData = new ColumnData();
                                            columnData.ColumnNm = field;
                                            columnList.Add(columnData);
                                            i++;
                                        }
                                        columnCnt = i;
                                    }
                                    else if (rowCnt == 1)
                                    {
                                        // データ型の格納
                                        int i = 0;
                                        foreach (string field in csvRow)
                                        {
                                            if (i >= columnCnt)
                                            {   // カラム数チェック
                                                dgvFileList[1, row].Style.BackColor = Color.Pink;
                                                // メッセージ:{0}[{1}行目]:データ型項目数がヘッダ項目数を超えています。
                                                lblMessage.Text = string.Format(Properties.HySAddinLsor2VieweEXEResources.MSG_ERROR_DATA_TYPE_ITEMS_EXCEEDS_HEADER_ITEMS,
                                                    inputFile.FileId, lineCnt);
                                                lblMessage.ForeColor = Color.Red;
                                                e.Cancel = true;
                                                return; // 処理中断
                                            }
                                            columnList[i].DataType = field;
                                            i++;
                                        }
                                    }
                                    else if (rowCnt == 2)
                                    {
                                        // 単位の格納
                                        int i = 0;
                                        foreach (string field in csvRow)
                                        {
                                            if (i >= columnCnt)
                                            {   // カラム数チェック
                                                dgvFileList[1, row].Style.BackColor = Color.Pink;
                                                // メッセージ:{0}[{1}行目]:単位項目数がヘッダ項目数を超えています。
                                                lblMessage.Text = string.Format(Properties.HySAddinLsor2VieweEXEResources.MSG_ERROR_UNIT_ITEMS_EXCEEDS_HEADER_ITEMS,
                                                    inputFile.FileId, lineCnt);
                                                lblMessage.ForeColor = Color.Red;
                                                e.Cancel = true;
                                                return; // 処理中断
                                            }
                                            columnList[i].UnitType = field;
                                            i++;
                                        }
                                        // ヘッダ3行の格納
                                        inputFile.ColumnList = columnList;
                                    }
                                    else
                                    {
                                        // データの格納
                                        int i = 0;
                                        csvData.Add(new string[columnCnt]); // 列を用意
                                        foreach (string field in csvRow)
                                        {
                                            if (i >= columnCnt)
                                            {   // カラム数チェック
                                                dgvFileList[1, row].Style.BackColor = Color.Pink;
                                                // メッセージ:{0}[{1}行目]:データ数がヘッダ項目数を超えています。
                                                lblMessage.Text = string.Format(Properties.HySAddinLsor2VieweEXEResources.MSG_ERROR_DATA_EXCEEDS_HEADER_ITEMS,
                                                    inputFile.FileId, lineCnt);
                                                lblMessage.ForeColor = Color.Red;
                                                e.Cancel = true;
                                                return; // 処理中断
                                            }
                                            ((string[])csvData[rowCnt - 3])[i] = field;
                                            i++;
                                        }
                                    }
                                    rowCnt++;
                                }
                                inputFile.CsvData = csvData;
                            }
                        }
                        catch
                        {
                            dgvFileList[1, row].Style.BackColor = Color.Pink;
                            // メッセージ:ファイル形式が不正です。
                            lblMessage.Text = Properties.HySAddinLsor2VieweEXEResources.MSG_ERROR_INVALID_FILE_FORMAT;
                            lblMessage.ForeColor = Color.Red;
                            e.Cancel = true;
                            return;

                        }
                        dgvFileList[1, row].Style.BackColor = Color.White;

                        // キー項目名称のチェック
                        if (String.Compare(inputFile.ColumnList[0].ColumnNm, CommonData.KEY_RIVER_NM, true) != 0
                            || String.Compare(inputFile.ColumnList[1].ColumnNm, CommonData.KEY_TOPO_ID, true) != 0
                            || String.Compare(inputFile.ColumnList[2].ColumnNm, CommonData.KEY_SLICE_NO, true) != 0
                            || String.Compare(inputFile.ColumnList[3].ColumnNm, CommonData.KEY_SUM_DISTANCE, true) != 0)
                        {
                            dgvFileList[1, row].Style.BackColor = Color.Pink;
                            // メッセージ:キー項目名称に誤りがあります。
                            lblMessage.Text = Properties.HySAddinLsor2VieweEXEResources.MSG_ERROR_INCORRECT_KEY_FIELD_NAME;
                            lblMessage.ForeColor = Color.Red;
                            errFlg = true;
                        }
                        else if (row <= 0)
                        {
                            // 計算入力ファイルのキー項目を格納
                            for (int i = 0; i < inputFile.CsvData.Count; i++)
                            {
                                string key =
                                    ((string[])inputFile.CsvData[i])[0] + "," +
                                    ((string[])inputFile.CsvData[i])[1] + "," +
                                    ((string[])inputFile.CsvData[i])[2] + "," +
                                    ((string[])inputFile.CsvData[i])[3];
                                keyList.Add(key);
                            }
                        }
                        else
                        {
                            // 結果出力ファイルの場合は、結果入力ファイルとのキー項目一致チェック
                            if (inputFilelist[0].CsvData.Count != inputFile.CsvData.Count)
                            {
                                // 行数のチェック
                                dgvFileList[1, row].Style.BackColor = Color.Pink;
                                // メッセージ:データ行数が計算入力ファイルと一致しません。
                                lblMessage.Text = Properties.HySAddinLsor2VieweEXEResources.MSG_ERROR_DATA_ROWS_NUM_MISMATCH_CALCULATE_INPUT;
                                lblMessage.ForeColor = Color.Red;
                                errFlg = true;
                            }
                            else
                            {
                                Boolean noMatch = false;
                                try
                                {
                                    ArrayList keyListClone = (ArrayList)keyList.Clone();
                                    for (int i = 0; i < inputFilelist[0].CsvData.Count; i++)
                                    {
                                        string key =
                                            ((string[])inputFile.CsvData[i])[0] + "," +
                                            ((string[])inputFile.CsvData[i])[1] + "," +
                                            ((string[])inputFile.CsvData[i])[2] + "," +
                                            ((string[])inputFile.CsvData[i])[3];
                                        int index = keyListClone.IndexOf(key);
                                        if (index < 0)
                                        {
                                            noMatch = true;
                                            break;
                                        }
                                        else
                                        {
                                            keyListClone.RemoveAt(index);
                                        }
                                    }
                                }
                                catch
                                {
                                    noMatch = true;
                                }
                                if (noMatch)
                                {
                                    dgvFileList[1, row].Style.BackColor = Color.Pink;
                                    // メッセージ:キー項目が計算入力ファイルと一致しません。
                                    lblMessage.Text = Properties.HySAddinLsor2VieweEXEResources.MSG_ERROR_KEY_FIELDS_MISMATCH_CALCULATION_INPUT;
                                    lblMessage.ForeColor = Color.Red;
                                    errFlg = true;
                                }
                            }
                        }
                    }
                    else
                    {
                        inputFile.FileNm = null;
                    }
                    inputFilelist.Add(inputFile);
                }

                if (errFlg)
                {
                    e.Cancel = true;
                    return;
                }

                // 計算入力ファイルのCSVから、河川リストを取得して登録
                List<RiverData> inputRiverlist = new List<RiverData>();
                inputRiverlist = this._commonData.RiverList;
                RiverData riverData;
                // 項目インデックスを取得
                int columnIdx_River = Util.GetColumnIndex(inputFilelist[0], CommonData.KEY_RIVER_NM);
                int columnIdx_Topo = Util.GetColumnIndex(inputFilelist[0], CommonData.KEY_TOPO_ID);
                for (int i = 0; i < inputFilelist[0].CsvData.Count; i++)
                {
                    riverData = new RiverData();
                    // CSVからデータ取得
                    string riverNm = ((string[])inputFilelist[0].CsvData[i])[columnIdx_River];
                    string topoId = ((string[])inputFilelist[0].CsvData[i])[columnIdx_Topo];
                    // すでに登録されているかチェック
                    bool existFlg = false;
                    for (int j = 0; j < inputRiverlist.Count; j++)
                    {
                        if (riverNm == inputRiverlist[j].RiverNm)
                        {
                            existFlg = true;
                            // topoIDのみ更新
                            inputRiverlist[j].TopoId = topoId;
                        }
                    }

                    if (!existFlg)
                    {
                        riverData.RiverNm = riverNm;
                        riverData.TopoId = topoId;
                        inputRiverlist.Add(riverData);
                    }
                }

                // inputRiverlistから、存在しない河川を取り除く
                bool riverFlg = false;
                for (int i = 0; i < inputRiverlist.Count; i++)
                {
                    for (int j = 0; j < inputFilelist[0].CsvData.Count; j++)
                    {
                        if (inputRiverlist[i].RiverNm == ((string[])inputFilelist[0].CsvData[j])[columnIdx_River])
                        {
                            riverFlg = true;
                            break;
                        }
                    }
                    if (!riverFlg)
                    {
                        inputRiverlist.RemoveAt(i);
                        i--;
                    }
                    else
                    {
                        riverFlg = false;
                    }
                }

                this._commonData.FileList = inputFilelist;
                this._commonData.RiverList = inputRiverlist;
            }
        }

        #endregion

        #endregion
    }
}
