//ライセンス情報はAgeOnフォルダのLISENCEフォルダを参照してください
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Diagnostics;
namespace nispi
{
    class MatchUrlData
    {
        public string place;
        public string boardUrl;
        public string boardName;
        public string line;

        public MatchUrlData(string place, string boardUrl, string boardName, string line)
        {
            this.place = place;
            this.boardUrl = boardUrl;
            this.boardName = boardName;
            this.line = line;
        }
    }

    class GetScreeningData
    {
        public static Dictionary<string, List<MatchUrlData>> placeDic;
        ProgressBarForm progressBarForm;

        public static Mutex mutex = new Mutex(false, "GetScreeningData");
        private bool stoppingBool;

        int progressMax = 0;

        public GetScreeningData()
        {
            stoppingBool = false;
        }

        public void StartScreening()
        {
            progressBarForm = new ProgressBarForm(new ProgressBarForm.SimpleMethod(StopDownloading));
            //progressBarForm.SetUpTwo();
            Thread t = new Thread(new ThreadStart(progressBarForm.SetUpTwo));
            t.IsBackground = true;
            t.Start();
            stoppingBool = false;

            Const.mapForm.mapMainForm.Invoke((Action)(() => progressBarForm.textLabel.Text = "受信しています"));
            
            ScreeningSubjectList();
            
            Const.form.mainForm.Invoke((Action)(() => progressBarForm.textLabel.Text = "解析しています"));
            
            WriteScreeningData();
            
            Const.form.mainForm.Invoke((Action)(() => progressBarForm.progressBar.Value = progressMax));

            Const.form.mainForm.Invoke((Action)(() => progressBarForm.textLabel.Text = "終了しました"));

            System.Threading.Thread.Sleep(1000);
            Const.mapForm.lastUpdateToolStripStatusLabel.Text = "最終更新：" +DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString();
            FileIO.SaveUnicode("Setting", "lastupdate.txt", Const.mapForm.lastUpdateToolStripStatusLabel.Text);

            //Const.form.mainForm.Invoke(new ProgressBarForm.SimpleMethod(progressBarForm.Closing));
            progressBarForm.popUp.Invoke((Action)(() => progressBarForm.Closing()));
        }

        public void StopDownloading()
        {
            mutex.WaitOne();
            this.stoppingBool = true;
            mutex.ReleaseMutex();
        }

        public bool StoppingTest()
        {
            mutex.WaitOne();
            if (stoppingBool == true)
            {
                mutex.ReleaseMutex();
                return true;
            }
            else
            {
                mutex.ReleaseMutex();
                return false;
            }
        }
        

        private void WriteScreeningData()
        {
            string screeningPath = ".ageon" + Path.DirectorySeparatorChar +
                "cache" + Path.DirectorySeparatorChar +
                "screening" + Path.DirectorySeparatorChar;

            foreach (KeyValuePair<string, List<MatchUrlData>> pair in placeDic)
            {
                if (this.StoppingTest() == true) break;
                ThreadInfo threadInfo = new ThreadInfo();

                foreach (MatchUrlData matchUrlData in pair.Value)
                {
                    SubjectUtil.ParseSubjectLine(threadInfo, matchUrlData.line, matchUrlData.boardUrl);
                }

                //生存ログを読み込む
                string str = FileIO.ReadUnicode(screeningPath + pair.Key, "subject_info.txt");
                //生存ログを照会する
                if ((str != null) && (str.Length != 0))
                {
                    ThreadInfo oldInfo = SubjectUtil.ParseSubjectInfoLines(str, "subject_info.txt");
                    CompotionList(oldInfo.threadDataList, threadInfo.threadDataList);
                    oldInfo.threadDataList.Clear();
                    oldInfo.threadDataList = null;
                }
                //そのままの順番で生存ログを保存する
                SaveToSubjectInfo(threadInfo, pair.Key, "subject_info.txt");
                //情報ファイルを保存する
                SaveInfomation(threadInfo.threadDataList.Count, pair.Key, "subject_info.info.txt");


                //日時順に並び替える
                threadInfo.threadDataList.Sort(BoadListSort.CompareOpenTime);

                int index = -1;
                string dateTime = "";
                List<List<ThreadData>> threadListList = new List<List<ThreadData>>();
                //作成された日にちごとにリストに分ける
                foreach (ThreadData threadData in threadInfo.threadDataList)
                {
                    //先頭の１０文字が同じなら加える
                    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);

                    }
                }

                //日にちごとにログと照会した後に、まとめて書き込む
                foreach (List<ThreadData> threadList in threadListList)
                {

                    //日時にあうログを読み込む
                    string fileNameOnly = threadList[0].openTimeString.Substring(0, 10).Replace('/', '_');
                    string fileName = fileNameOnly + ".txt";
                    str = FileIO.ReadUnicode(screeningPath + pair.Key, 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;
                    }
                    else
                        newList = threadList;

                    //ログを書き込む
                    SaveToSubjectList(newList, pair.Key, fileName);
                    //情報を書き込む
                    SaveInfomation(newList.Count, pair.Key, fileNameOnly + ".info.txt");
                    threadList.Clear();
                    newList.Clear();
                }
            }
        }

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

        //subject_info.txtに保存する
        private void SaveToSubjectInfo(ThreadInfo threadInfo, string boardID, string fileName)
        {
            StringBuilder sb = new StringBuilder();

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

        public static void SaveToSubjectList(List<ThreadData> threadList, 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 +
                    "screening" + 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)
                        {
                            newThreadData.readNum = oldThreadData.readNum;
                            oldList.Remove(oldThreadData);
                            break;
                        }
                    }
                }
            }
        }

        private void ScreeningSubjectList()
        {
            List<MatchUrlData> matchList = new List<MatchUrlData>();

            try 
            { 
                placeDic.Clear();
            }
            catch (System.Exception ex)
            {
                //Const.debugForm.OutPutDebug("Map", ex);
            }

            placeDic = new Dictionary<string, List<MatchUrlData>>();
            //ローカルファイルからＵＲＬの行を得る
            string str = FileIO.ReadCurrentShiftJis("data", "mapsubject_url_list.txt");
            string[] rows = str.Split(new char[] { '\r', '\n' });

            Const.form.mainForm.Invoke((Action)(() => progressBarForm.progressBar.Maximum = progressMax =  rows.Length + 10));
            int count = 0;

            foreach (string line in rows.Where(a => a.Length > 0))
            {
                count += 1;
                Const.form.mainForm.Invoke((Action)(() => progressBarForm.progressBar.Value = count*2));
                if (StoppingTest() == true) break;

                //ＵＲＬと板名に分ける
                string[] subjectData = line.Split(new char[] { ',' });
                //ダウンロードする
                //string data = Download(subjectData[0] + "subject.txt");
                //ＵＲＬが変わっていることに対応
                subjectData[0] = GetBoardUrlFromName(subjectData[1]);
                if (subjectData[0].Length == 0) continue;
                string data = Download(subjectData[0] + "subject.txt");
                
                if (data.Length == 0) continue;

                //ダウンロードした行のリストを得る
                string[] rows2 = data.Split(new char[] { '\r', '\n' });
                //一行ずつ調査する
                foreach (string line2 in rows2.Where(a => a.Length > 0))
                {
                    //検索ワードのリストで総当たりする
                    foreach (List<string> list in BasicMapData.simpleWordList)
                    {
                        if (list.Any(a => line2.Contains(a)))
                        {
                            //既に登録されている地名であれば登録。なければ新規登録。
                            if (placeDic.ContainsKey(list[1]) == true)
                                placeDic[list[1]].Add(new MatchUrlData(list[1], subjectData[0], subjectData[1], line2));
                            else
                            {
                                placeDic[list[1]] = new List<MatchUrlData>();
                                placeDic[list[1]].Add(new MatchUrlData(list[1], subjectData[0], subjectData[1], line2));
                            }
                        }
                    }
                }

            }
        }

        private string Download(string url)
        {
            string str = "";
            DownloadSubject ds = new DownloadSubject();
            if (true == ds.DownloadSubjectText(url))
            {
                str = ds.httpResData;
            }
            else
                return "";

            return str;
        }

        private string GetBoardUrlFromName(string searchText)
        {
            int selectedNodeNode = 0;
            int selectedNode = 0;

            for (int index = selectedNode; MainFormConst.boardIndexTabMain.scBoardIndexView.boardIndexControls.treeViewParts.control.Nodes.Count > index; ++index)
            {
                for (int index2 = selectedNodeNode; MainFormConst.boardIndexTabMain.scBoardIndexView.boardIndexControls.treeViewParts.control.Nodes[index].Nodes.Count > index2; ++index2)
                {
                    if (true == MainFormConst.boardIndexTabMain.scBoardIndexView.boardIndexControls.treeViewParts.control.Nodes[index].Nodes[index2].Text.Equals(searchText))
                    {
                        //選択する
                        string url = MainFormConst.boardIndexTabMain.scBoardIndexView.boardIndexControls.treeViewParts.control.Nodes[index].Nodes[index2].Name;
                        return url;
                    }
                }

            }
            return "";
        }
    }
}
