//ライセンス情報はAgeOnフォルダのLISENCEフォルダを参照してください
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Net;

namespace nispi.controlclass
{
    class ListViewPartMethodUtil
    {

        public static void GetLogData(BoardViewCommon boardView, ref string typeName, ref string boardID)
        {
            typeName = Util.BoardUrlToBoardTypeName(boardView.board_url);
            boardID = Util.BoardUrlToBoardID(boardView.board_url);
        }

        public delegate void SearchAndChangeNumDelegate(ThreadInfo threadInfo, string datUrl, string resNum);

        public static void ChangeReadNum(BoardViewCommon boardView, ListViewParts listViewPart, string type)
        {
            //一応同じか確認
            if (boardView.board_url == listViewPart.Name)
            {
                //リストを読み込む
                ThreadInfo threadInfo;

                if (boardView.bvTimeExtraction.threadInfo != null)
                    threadInfo = boardView.bvTimeExtraction.threadInfo;
                else if (boardView.wordExtraction.threadInfo != null)
                    threadInfo = boardView.wordExtraction.threadInfo;
                else if (boardView.threadInfo != null)
                    threadInfo = boardView.threadInfo;
                else
                    return;


                string typeName = "";
                string boardID = "";
                GetLogData(boardView, ref typeName, ref boardID);

                ThreadInfo changedThreadInfo = new ThreadInfo(); 
                
                //複数選択に対応
                foreach (int num in listViewPart.GetSelectedIndices())
                {
                    if (type.Equals("read") == true)
                    {
                        threadInfo.threadDataList[num].readNum = threadInfo.threadDataList[num].resNum;
                        threadInfo.threadDataList[num].noReadNum = "0";
                    }
                    else if (type.Equals("nonRead") == true)
                    {
                        threadInfo.threadDataList[num].readNum = "0";
                        threadInfo.threadDataList[num].noReadNum = threadInfo.threadDataList[num].resNum;
                    }

                    //表示されている外見を改変する
                    Const.form.mainForm.Invoke((Action)(() => boardView.boardListControls.listViewParts.items[num].SubItems_5_Text = threadInfo.threadDataList[num].readNum));
                    Const.form.mainForm.Invoke((Action)(() => boardView.boardListControls.listViewParts.items[num].SubItems_6_Text = threadInfo.threadDataList[num].noReadNum));

                    //書き換える予定のリストの一行を加えてゆく（後から過去ログにも適用してゆく）
                    changedThreadInfo.threadDataList.Add(threadInfo.threadDataList[num]);
                }
                //過去ログに対して書き込みを行う      
                //try
                //{
                    WriteToLog(typeName, boardID, changedThreadInfo, boardView.threadInfo, boardView.bvTimeExtraction.threadInfo, boardView.wordExtraction.threadInfo, type);
               // }
                //catch { ; }
                //ログに書き込む
                boardView.WriteLogFile(boardView.threadInfo.threadDataList);
                //suject.info.txtから過去ログを作り出して書き込む
                
                //boardView.bvTimeExtraction.MakeExtractionThreadInfo();
                

                //表示しなおす

                //Const.form.mainForm.Invoke(new Action(boardView.Write_List_Dele));
            }
        }

        public static void WriteToLog(string typeName, string boardID, ThreadInfo changeThreadInfo, ThreadInfo subjectThreadInfo,ThreadInfo timeThreadInfo, ThreadInfo wordThreadInfo, string type)
        {
            //日時順に並び替える
            changeThreadInfo.threadDataList.Sort(BoadListSort.CompareOpenTime);

            int index = -1;
            string dateTime = "";
            List<List<ThreadData>> threadListList = new List<List<ThreadData>>();

            //作成された日にちごとにリストに分ける
            foreach (ThreadData threadData in changeThreadInfo.threadDataList)
            {
                //threadData.readNum = 
                //先頭の１０文字が同じなら加える
                if (threadData.openTimeString.Substring(0, 10).Equals(dateTime) == true)
                    threadListList[index].Add(threadData);
                //違うなら新しくリストを追加して加える
                else
                {
                    index += 1;
                    threadListList.Add(new List<ThreadData>());
                    threadListList[index].Add(threadData);
                    dateTime = threadData.openTimeString.Substring(0, 10);
                }
            }

            //try
            //{
                //日にちごとにログと照会した後に、まとめて書き込む
                foreach (List<ThreadData> threadList in threadListList)
                {
                    //日時にあうログを読み込む
                    string fileNameOnly = threadList[0].openTimeString.Substring(0, 10).Replace('/', '_');
                    string fileName = fileNameOnly + ".txt";
                    string str = FileIO.ReadUnicode(
                        ".ageon" + Path.DirectorySeparatorChar +
                        "cache" + Path.DirectorySeparatorChar +
                        typeName + Path.DirectorySeparatorChar +
                        boardID, fileName);

                    List<ThreadData> newList;

                    //ログと比較して整理する
                    if ((str != null) && (str.Length != 0))
                    {
                        ThreadInfo oldInfo = SubjectUtil.ParseSubjectInfoLines(str, fileName);
                        //肝・書き換える
                        CompotionList(oldInfo.threadDataList, threadList);

                        newList = threadList.Concat(oldInfo.threadDataList).ToList();

                        oldInfo.threadDataList.Clear();
                        oldInfo.threadDataList = null;

                        oldInfo = SubjectUtil.ParseSubjectInfoLines(str, fileName);
                        //subject.txtのデータメンバを書き換える
                        CompotionList2(subjectThreadInfo.threadDataList, threadList);
                        //丁度抽出されている日にちによるリストを書き換える
                        if (timeThreadInfo != null)
                            CompotionList2(timeThreadInfo.threadDataList, threadList);
                        //丁度抽出されているワードによるリストを書き換える
                        if (wordThreadInfo != null)
                            CompotionList2(wordThreadInfo.threadDataList, threadList);
                    }
                    else
                        newList = threadList;

                    //ログを書き込む
                    SaveToSubjectList(newList, typeName, boardID, fileName);

                    //情報を書き込む
                    SaveInfomation(newList.Count, typeName, boardID, fileNameOnly + ".info.txt");
                    threadList.Clear();
                    newList.Clear();
                }
            //}
            //catch (Exception e)
            //{
            //    index = 0;
            //}
        }

        public static void SaveInfomation(int count, string typeName, string boardID, string fileName)
        {
            FileIO.SaveUnicode(".ageon" + Path.DirectorySeparatorChar + "cache" + Path.DirectorySeparatorChar +
                typeName + Path.DirectorySeparatorChar + boardID, fileName, count.ToString() + "\r\n");
        }

        public static void SaveToSubjectList(List<ThreadData> threadList, string typeName, string boardID, string fileName)
        {
            StringBuilder sb = new StringBuilder();

            foreach (ThreadData threadData in threadList)
            {
                sb.Append(SubjectUtil.MakeSubjectInfoLine(threadData));
            }
            FileIO.SaveUnicode(".ageon" + Path.DirectorySeparatorChar + "cache" + Path.DirectorySeparatorChar +
                    typeName + Path.DirectorySeparatorChar + boardID, fileName, sb.ToString());
        }

        public static void CompotionList(List<ThreadData> oldList, List<ThreadData> newList)
        {
            if ((oldList != null) && (oldList.Count != 0))
            {
                foreach (ThreadData newThreadData in newList)
                {
                    foreach (ThreadData oldThreadData in oldList)
                    {
                        if (newThreadData.datUrl.Equals(oldThreadData.datUrl) == true)
                        {
                            oldThreadData.readNum = newThreadData.readNum;
                            oldThreadData.noReadNum = newThreadData.noReadNum;

                            oldList.Remove(oldThreadData);
                            break;
                        }
                    }
                }
            }
        }
        //nullチェックとコメントアウトしたところだけがCompotionListと違う
        public static void CompotionList2(List<ThreadData> oldList, List<ThreadData> newList)
        {
            if ((oldList != null) && (oldList.Count != 0) &&  (newList != null) && (newList.Count != 0))
            {
                foreach (ThreadData newThreadData in newList)
                {
                    foreach (ThreadData oldThreadData in oldList)
                    {
                        if (newThreadData.datUrl.Equals(oldThreadData.datUrl) == true)
                        {
                            oldThreadData.readNum = newThreadData.readNum;
                            oldThreadData.noReadNum = newThreadData.noReadNum;

                            //oldList.Remove(oldThreadData);
                            break;
                        }
                    }
                }
            }
        }
        public static string ReadKakoLog(string typeName, string boardID, string fileName)
        {
            string str = FileIO.ReadUnicode(
                ".ageon" + Path.DirectorySeparatorChar +
                "cache" + Path.DirectorySeparatorChar +
                typeName + Path.DirectorySeparatorChar +
                boardID, fileName);
            return str;
        }


        public static void SearchAndChangeReadNum(ThreadInfo threadInfo, string datUrl, string resNum)
        {
            foreach (ThreadData threadData in threadInfo.threadDataList)
            {
                if (threadData.datUrl.Equals(datUrl) == true)
                {
                    threadData.readNum = resNum;
                    threadData.noReadNum = "0";
                    break;
                }
            }
        }
        public static void SearchAndChangeNoReadNum(ThreadInfo threadInfo, string datUrl, string resNum)
        {
            foreach (ThreadData threadData in threadInfo.threadDataList)
            {
                if (threadData.datUrl.Equals(datUrl) == true)
                {
                    threadData.noReadNum = resNum;
                    threadData.readNum = "0";
                    break;
                }
            }
        }

        //保存を行うスレッド
        public static void DownloadFileThread(object o)
        {
            try
            {
                DownloadFilePram param = (DownloadFilePram)o;
                WebClient client = new WebClient();
                Uri u = new Uri(param.donwloadUrl);
                string str = client.DownloadString(u);
                SaveFile(param.fileName, str);
            }
            catch { ;}
            return;
        }

        //保存スレッドから呼ばれるメソッド
       public static void SaveFile(string fullName, string str)
        {
            string[] data = fullName.Split(Path.DirectorySeparatorChar);
            string fileName = data[data.Length - 1];
            data[data.Length - 1] = "";
            string dir = string.Join(Path.DirectorySeparatorChar.ToString(), data);

            if (File.Exists(dir) == false)
            {
                DirectoryInfo di = new DirectoryInfo(dir);
                di.Create();
            }

            try
            {
                using (FileStream fsw = new FileStream(dir + fileName, FileMode.Create))
                {
                    using (StreamWriter sw = new StreamWriter(fsw, System.Text.Encoding.Unicode))
                    {
                        sw.Write(str);
                        sw.Flush();
                        sw.Close();
                        fsw.Close();
                    }
                }
            }
            catch
            {
                return;
            }
        }

        //保存するための情報を得るダイアログ
        public static string OpenSaveFileDialog(string type, string fileName)
        {
            System.Windows.Forms.SaveFileDialog saveDlg = new System.Windows.Forms.SaveFileDialog();

            saveDlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            saveDlg.FileName = fileName;

            if (type.Equals("html") == true)
                saveDlg.Filter = "HTML File (*.html)|*.html ";
            else
                saveDlg.Filter = "DAT File (*.dat)|*.dat ";

            if (saveDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                return saveDlg.FileName;
            }
            else
                return "";
        }

        //特定のログを削除する
        public static void DeleteFile(string datUrl)
        {
            string dir = Util.DatUrlToDatDirPath(datUrl);
            string dat_file_name = Util.DatUrlToDatFileName(datUrl);

            string fullName = dir + Path.DirectorySeparatorChar + dat_file_name;

            try
            {
                //ログファイルを削除する
                System.IO.File.Delete(fullName);
                //ログファイルの情報ファイルも削除する
                System.IO.File.Delete(fullName + ".info");
            }
            catch
            {
                return;
            }
        }
    }
    //ダウンロードをするスレッドで使うパラメータ
    class DownloadFilePram
    {
        public string donwloadUrl;
        public string fileName;

        public DownloadFilePram(string downloadUrl, string fileName)
        {
            this.donwloadUrl = downloadUrl;
            this.fileName = fileName;
        }
    }
}
