﻿using System;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        //ソート可能リスト
        private static SortableBindingList<FilePath> sortlist = new SortableBindingList<FilePath>();

        //HTMLファイルとみなす拡張子
        private string[] htmlfiles = {".HTM", ".HTML", ".PHP"};

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            #region DataGridView設定
            //データソース指定▲DGVオブジェクトがこの段階で作成される▼
            dataGridView1.DataSource = sortlist;

            //※表スタイル指定
            //※一番左端の項目列（RowHeader）を消す
            dataGridView1.RowHeadersVisible = false;
            //※任意の行追加不可
            dataGridView1.AllowUserToAddRows = false;
            //※DataGridView1の列のテキストを変更する
            dataGridView1.Columns[0].HeaderText = "現在のファイル名";
            dataGridView1.Columns[1].HeaderText = "新しいファイル名";
            dataGridView1.Columns[2].HeaderText = "ディレクトリ";

            dataGridView1.AllowUserToResizeColumns = true;

            //初期列幅
            dataGridView1.Columns[0].Width = 300; 
            dataGridView1.Columns[1].Width = 300;
            dataGridView1.Columns[2].Width = 200;

            //※フォント設定（全セル適応）
            dataGridView1.DefaultCellStyle.Font = new Font("ＭＳ ゴシック", 14);

            //ヘッダーとすべてのセルの内容に合わせて、列の幅を自動調整する
            //dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

            //ヘッダーとすべてのセルの内容に合わせて、行の高さを自動調整する
            dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;

            dataGridView1.Refresh();
            #endregion

            //※アクセシビリティの文脈でも、やはり昔も今も変わらずラジオボタンには初期値をつけるのが望ましいとされているようです。
            //デフォルト変更
            radioButton2.Checked = true;

            //webBrowser1.Visible = false;
            toolStripComboBox1.SelectedIndex = 0;
        }

        #region ファイル読み込み処理
        private void Open_Files()
        {
            OpenFileDialog ofd = new OpenFileDialog();

            ofd.Title = "ファイルを選択してください";

            //ダイアログボックスを閉じる前に現在のディレクトリを復元するようにする
            ofd.RestoreDirectory = true;

            //複数のファイルを選択できるようにする
            ofd.Multiselect = true;

            //ダイアログを表示する
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                foreach (string fn in ofd.FileNames)
                {
                    sortlist.Add(new FilePath(fn));
                }
            }
        }
        #endregion

        #region 各ボタン処理
        //▲ファイルの読み込み▼
        private void button1_Click(object sender, EventArgs e)
        {
            Open_Files();
        }

        //キャンセル
        private void button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        #region 置換処理
        //置換実行
        private void button3_Click(object sender, EventArgs e)
        {
            string srchstr = SrchcomboBox.Text;
            string repstr = RepcomboBox.Text;

            if (srchstr == "") { return; }

            foreach (FilePath d in sortlist)
            {
                if (RegExpcheckBox.Checked)
                {
                    //正規表現でリネーム
                    d.NewFileName = Regex.Replace(d.NewFileName, srchstr, repstr);
                }
                else
                {
                    d.NewFileName = d.NewFileName.Replace(srchstr, repstr);
                }
            }

            //入力値の重複チェック（アイテム内に無いときは-1が返る）
            if (SrchcomboBox.Items.IndexOf(SrchcomboBox.Text) == -1)
            {
                //アイテム一覧の一番上に登録
                SrchcomboBox.Items.Insert(0, SrchcomboBox.Text);
            }
            if (RepcomboBox.Items.IndexOf(RepcomboBox.Text) == -1)
            {
                //アイテム一覧の一番上に登録
                RepcomboBox.Items.Insert(0, RepcomboBox.Text);
            }

            dataGridView1.Refresh();
        }
        #endregion

        ////リネームモード切り換え
        //文字化け修正〔デフォルト〕
        private void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton1.Checked)
            {
                foreach (FilePath d in sortlist)
                {
                    d.NewFileName = d.GetUTFDecodeName();
                }
                dataGridView1.Refresh();
            }
        }

        //通常リネーム
        private void radioButton2_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton2.Checked)
            {
                foreach (FilePath d in sortlist)
                {
                    d.NewFileName = d.OrgFileName;
                }
                dataGridView1.Refresh();
            }
        }


        #region HTML タイトルタグリネーム
        //HTML タイトルタグでリネーム
        private void radioButton3_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton3.Checked)
            {
                string line = "";
                string title = "";

                // すべてのタグ
                Regex htmlTags = new Regex("<.*?>", RegexOptions.Singleline);

                foreach (FilePath d in sortlist)
                {
                    line = GetHtmlDoc(d.GetOrgFullpath(), "UTF-8");

                    if (line == "") { continue; }

                    if (line.Contains("charset"))
                    {
                        if (line.Contains("Shift_JIS") || line.Contains("Shift-JIS") || line.Contains("shift_jis") || line.Contains("\"shift_jis\""))
                        {
                            line = GetHtmlDoc(d.GetOrgFullpath(), "Shift_JIS");
                        }
                        else if (line.Contains("EUC-JP") || line.Contains("EUC-JP") || line.Contains("euc-jp"))
                        {
                            line = GetHtmlDoc(d.GetOrgFullpath(), "euc-jp");
                            //line = GetHtmlDoc(d.GetOrgFullpath(), "Unknown");
                        }
                    }
                    else
                    {
                        line = GetHtmlDoc(d.GetOrgFullpath(), "Unknown");
                    }

                    //MessageBox.Show(line);
                    //<title></title>で囲まれた部分を抜き出す
                    //最短マッチに変更⇒任意の1文字の繰り返しを最短で切り上げるため、(.*)に「?」を入れます。
                    Match matche = Regex.Match(line, "<[title|TITLE]>.*?</[title|TITLE]>");
 
                    if (matche.Value == "")
                    {
                        d.NewFileName = "NOTITLE" + Path.GetExtension(d.OrgFileName);
                    }
                    else
                    {
                        //タグ削除
                        title = htmlTags.Replace(matche.Value, "");
                        //MessageBox.Show(title);

                        //禁則処理
                        title = FilePath.File_system_prohibition_processing(title);
                        //前後の空白等を削除
                        title = title.Trim();
                        //リストボックス2に登録
                        d.NewFileName = title + Path.GetExtension(d.OrgFileName);
                    }

                    //ファイル一つごとに更新
                    dataGridView1.Refresh();
                }
            }
            //最終更新すること！！！
            dataGridView1.Refresh();
        }

        private string GetHtmlDoc(string uri, string encoding)
        {
            //HTMLタイトル取得用
            var webBrowser1 = new WebBrowser();
            //WebBrowser webBrowser1;
            string htmldata = "";
            webBrowser1.ScriptErrorsSuppressed = true;

            //HTMLファイル以外は除外
            if (!htmlfiles.Contains(Path.GetExtension(@uri).ToUpper())) { return ""; }

            //文字コードセット不明時
            //強制ブラウザモード指定時
            if (encoding == "Unknown" || checkBox2.Checked)
            {
                //webBrowser1.Visible = false;

                // タイムアウト時間（3秒）
                TimeSpan timeout = new TimeSpan(0, 0, 3);

                // Webページを表示
                webBrowser1.Navigate("file://" + @uri);

                bool done = false;
                DateTime start = DateTime.Now;

                while (done == false)
                {
                    if (DateTime.Now - start > timeout)
                    {
                        // タイムアウト
                        break;
                    }
                    Application.DoEvents();
                }

                return "<title>" + webBrowser1.DocumentTitle + "</title>";
            }

            try
            {
                // 読み込みたいテキストを開く
                using (StreamReader sr = new StreamReader(@uri, Encoding.GetEncoding(encoding)))
                {
                    // テキストファイルをString型で読み込みコンソールに表示
                    htmldata = sr.ReadToEnd();
                    //return htmldata;
                }
            }
            catch (IOException ex)
            {
                MessageBox.Show(ex.Message);
            }
            catch (ExternalException ex)
            {
                MessageBox.Show(ex.Message);
            }

            if (encoding == "euc-jp")
            {
                //byte[] src_temp = System.Text.Encoding.ASCII.GetBytes(htmldata);
                //byte[] dest_temp = System.Text.Encoding.Convert(System.Text.Encoding.ASCII, System.Text.Encoding.ASCII, src_temp);
                //string ret = System.Text.Encoding.ASCII.GetString(dest_temp);
            }

            //改行コード全削してベタ詰めテキストを返す
            return htmldata.Replace("\r", "").Replace("\n", "").Replace("\t", "");
        }

        public string GetHtmlTitle(string src)
        {
            src = src.Replace("\r", "").Replace("\n", "").Replace("\t", "");

            //タイトルタグが無い時
            if (!src.Contains("</title>") && !src.Contains("</TITLE>"))
            {
                return "NOTITLE";
            }

            //Regex.Replace("{置換対象文字列}", "{正規表現パターン}", "{置換パターン}");
            src = Regex.Replace(src, "^.+<title[^>]*>", "");
            src = Regex.Replace(src, "^.+<TITLE[^>]*>", "");
            src = Regex.Replace(src, "</title>.*$", "");
            src = Regex.Replace(src, "</TITLE>.*$", "");

            //タイトルが空の時
            if (src == "") { src = "NOTITLE"; }

            return src;
        }
#endregion




        #region リネーム実行
        private void button4_Click(object sender, EventArgs e)
        {
            //リネームしたファイル数
            int cnt = 0;

            foreach (FilePath d in sortlist)
            {
                string oldpath = d.GetOrgFullpath();
                string newpath = d.GetNewFullpath();

                //変更ない場合、以下の処理をスキップ
                if (oldpath == newpath) { continue; }

                //ファイル名被り対策
                //同名のファイルが存在する場合
                if (File.Exists(newpath))
                {
                    if (checkBox1.Checked == true)
                    {
                        //連番処理
                        int No = 1;

                        string dir = Path.GetDirectoryName(newpath);
                        string ext = Path.GetExtension(newpath);
                        string nme = Path.GetFileNameWithoutExtension(newpath);

                        do
                        {
                            newpath = dir + "\\" + nme + " (" + No.ToString() + ")" + ext;
                            No++;
                        }
                        while (File.Exists(newpath));
                    }
                    else
                    {
                        //連番処理しないでスキップ
                        continue;
                    }
                }

                //元ファイルが消されてないかチェックしてからリネーム
                if (File.Exists(oldpath))
                {
                    try
                    {
                        File.Move(@oldpath, @newpath);
                        cnt++;
                    }
                    catch (System.IO.DirectoryNotFoundException ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                    catch (System.ArgumentException ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }

            MessageBox.Show(cnt.ToString() + "個のファイルをリネームしました。");
        }
        #endregion

        #region DataGridViewzへのドラッグ＆ドロップの実装
        private void dataGridView1_DragEnter(object sender, DragEventArgs e)
        {
            //コントロール内にドラッグされたとき実行される
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                //ドラッグされたデータ形式を調べ、ファイルのときはコピーとする
                e.Effect = DragDropEffects.Copy;
            else
                //ファイル以外は受け付けない
                e.Effect = DragDropEffects.None;
        }

        private void dataGridView1_DragDrop(object sender, DragEventArgs e)
        {
            //コントロール内にドロップされたとき実行される
            //ドロップされたすべてのファイル名を取得する
            var files = (string[])e.Data.GetData(DataFormats.FileDrop, false);
            //ListBoxに追加する
            foreach (string file in files)
            {
                sortlist.Add(new FilePath(file));
            }
            dataGridView1.Refresh();
        }
        #endregion

        #region メニューバー設定
        private void 終了XToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void ファイルを開くOToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Open_Files();
        }

        private void フォントFToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // FontDialog の新しいインスタンスを生成する (デザイナから追加している場合は必要ない)
            FontDialog fontDialog1 = new FontDialog();

            // 初期選択するフォントを設定する
            //fontDialog1.Font = dataGridView1.RowsDefaultCellStyle.Font;
            //' "ＭＳ ゴシック", 12pt, 標準, 日本語文字セット を既定値にする
            fontDialog1.Font = new System.Drawing.Font("ＭＳ ゴシック", 12, FontStyle.Regular, GraphicsUnit.Point, 128);

            // 初期選択する色を設定する
            fontDialog1.Color = dataGridView1.ForeColor;

            // 選択可能なフォントサイズの最大値を設定する
            //fontDialog1.MaxSize = 24;

            // 選択可能なフォントサイズの最小値を設定する
            fontDialog1.MinSize = 9;

            // 存在しないフォントやスタイルを選択すると警告を表示する (初期値 false)
            fontDialog1.FontMustExist = true;

            // 色を選択できるようにする (初期値 false)
            fontDialog1.ShowColor = true;

            // 取り消し線、下線、テキストの色などのオプションを指定可能にする (初期値 true)
            fontDialog1.ShowEffects = false;

            // [ヘルプ] ボタンを表示する (初期値 false)
            fontDialog1.ShowHelp = true;

            // [適用] ボタンを表示する (初期値 false)
            fontDialog1.ShowApply = true;

            // 非 OEM 文字セット、Symbol 文字セット、ANSI 文字セットを表示する (初期値 false)
            fontDialog1.ScriptsOnly = false;

            // 固定ピッチフォント (等幅フォント) だけを表示する (初期値 false)
            fontDialog1.FixedPitchOnly = true;

            // スクリプト ボックスの文字セットを変更可能にする (初期値 true)
            //fontDialog1.AllowScriptChange = true;

            // GDI におけるフォント表示をシミュレーション可能にする (初期値 true)
            //fontDialog1.AllowSimulations = true;

            // ベクタ フォントを表示する (初期値 true)
            //fontDialog1.AllowVectorFonts = true;

            // 縦書きフォントを表示する (初期値 true)
            //fontDialog1.AllowVerticalFonts = true;

            // ダイアログを表示し、戻り値が [OK] の場合は選択したフォントを textBox1 に適用する
            if (fontDialog1.ShowDialog() == DialogResult.OK)
            {
                dataGridView1.RowsDefaultCellStyle.Font = fontDialog1.Font;
                dataGridView1.RowsDefaultCellStyle.ForeColor = fontDialog1.Color;
            }

            // 不要になった時点で破棄する (正しくは オブジェクトの破棄を保証する を参照)
            fontDialog1.Dispose();
        }
        #endregion

        private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
        {
            //imageファイル以外は除外
            string[] imgfiles = { ".jpg", ".JPG", ".jpeg", ".JPEG", ".png", ".PNG", ".gif", ".GIF" };

            // メソッドの引数senderから対象となるDataGridViewオブジェクトを取得します。
            DataGridView dataGridView = (DataGridView)sender;

            // マウスがクリックされた座標(e.X, e.Y)から、DaataGridViewのHitTestメソッドでDataGridViewの位置情報を保持するHitTestInfoオブジェクトを取得します。
            DataGridView.HitTestInfo hitTestInfo = dataGridView.HitTest(e.X, e.Y);

            //ヘッダ除外 且つ 1列目だけ対象
            // HitTestInfoのRowIndexが行位置、ColumnIndexが列位置になります。
            // 表のデータ領域の左上のセルが(0, 0)になります。
            // 列ヘッダ、行ヘッダは"-1"位置になります。
            if (hitTestInfo.RowIndex >= 0 && hitTestInfo.ColumnIndex == 0)
            {
                string path = dataGridView1.Rows[hitTestInfo.RowIndex].Cells[2].Value + "\\" + dataGridView1.Rows[hitTestInfo.RowIndex].Cells[0].Value;
                if (imgfiles.Contains(Path.GetExtension(@path)))
                {
                    if (File.Exists(@path))
                    {
                        //PictureBoxコントロールに画像ファイルを表示します(ファイルロック問題回避版)
                        using (FileStream fs = new FileStream(@path, FileMode.Open, FileAccess.Read))
                        {
                            pictureBox1.Image = Image.FromStream(fs);
                            fs.Close();
                        }
                    }
                    else
                    {
                        //MessageBox.Show(@path + " は見つかりません。");
                        // ★★★画像を消去する★★★
                        pictureBox1.Image = null;
                    }
                }
                else
                { // ★★★画像消去★★★
                    pictureBox1.Image = null;
                }
            }
        }

        //全デフォルト化ボタン
        private void ListClearButton_Click(object sender, EventArgs e)
        {
            //dataGridView1.Columns.Clear();    //カラムヘッダまで消えるためNG
            dataGridView1.Rows.Clear();
            radioButton2.Checked = true;
        }

        private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            //※セルが一つも無い時は無効
            if (dataGridView1.CurrentCell == null) { return; }
            //※ヘッダダブルクリック時無効
            if (e.RowIndex < 0) { return; }
 
            //カレントセルのアドレス取得
            int rn = dataGridView1.CurrentCell.RowIndex;
            int cn = dataGridView1.CurrentCell.ColumnIndex;
           
            //元ファイル名列のみ参照
            if (cn != 0) { return; }

            string ext = Path.GetExtension(Convert.ToString(dataGridView1.Rows[rn].Cells[0].Value));
            if (!htmlfiles.Contains(Path.GetExtension(ext).ToUpper())) { return; }

            //Form2に送るテキスト
            //HTMLファイルを詠み込む
            string fullpath = Convert.ToString(dataGridView1.Rows[rn].Cells[2].Value) + "\\" + Convert.ToString(dataGridView1.Rows[rn].Cells[0].Value);
            string sendText = GetHtmlDoc(fullpath, toolStripComboBox1.Text);

            //Form2を開く
            if (sendText != null || sendText != "")
            {
                Form2.ShowHTMLSauceForm(sendText);
            }
        }

        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                string inpstr = textBox1.Text;

                /*
                 * 【ド・モルガンの法則】
                 *   NOT（a AND b）＝（NOT a）OR（NOT b）
                 *   NOT（a OR b）＝（NOT a）AND（NOT b）
                 */
                if (inpstr != "1" && inpstr != "2")
                {
                    MessageBox.Show("1でも2でもありません");
                }
                else
                {
                    MessageBox.Show("1もしくは2です");
                }
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            // カレントディレクトリの取得
            string stCurrentDir = System.Environment.CurrentDirectory;

            //自分自身の実行ファイルのパスを取得する
            string appPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

            //関連付けられたアプリケーションで開く
            System.Diagnostics.Process p = System.Diagnostics.Process.Start(appPath + "\\RegularExpression.html");
        }
    }
}
