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

using nispi.controlclass;

namespace nispi
{
    class tempParam
    {
        public BoardViewCommon view = null;
        public string str = null;
        public int threadLocalCount = 0;
    }
    class ThreadOpenParam
    {
        public string threadUrl;
        public string threadName;
        public ThreadOpenParam(string threadUrl, string threadName)
        {
            this.threadUrl = threadUrl;
            this.threadName = threadName;
        }
    }

    class BoardViewCommon
    {
        public string board_url = null;
        public string board_name = null;
        public string board_title = null;
        public string boardID = null;

        public ThreadInfo threadInfo;

        public BoardListControls boardListControls;

        public BoardViewTimeExtraction bvTimeExtraction;

        public WordExtraction wordExtraction;

        //直前のソートの方法を保存
        public int beforeNum = -1;

        //直前に選択されたリスト番号を無効にするため/
        public int currentnum = -1;

        public int threadLocalCount = 0;

        //現在のインスタンスで最新のダウンロードデータがあるかどうか
        public bool completeDownloading = false;

        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

        public AgeonMutex ageonMutex;

        public BoardViewCommon()
        {
            try
            {
                bvTimeExtraction = new BoardViewTimeExtraction(this as BoardViewCommon);
                wordExtraction = new WordExtraction(this as BoardViewCommon);
            }
            catch { ;}

            ageonMutex = new AgeonMutex();
            ageonMutex.Init();
        }
        public virtual void Dispoose()
        {
            try
            {
                ageonMutex.Terminate();

                int selectedIndex = Const.form.boardListTabControlParts.SelectedIndex;

                //お気に入りの場合はリターン
                if (selectedIndex == 0) return;


                Const.form.boardListTabControlParts.SuspendLayout();

                //初めに位置を設定する
                //SelectTabIndexFirst(selectedIndex);

                this.boardListControls.ResetControls();

                this.boardListControls.RemoveAllControls();

                MainFormConst.boardListTabMain.remove_view((BoardViewCommon)this);

                SelectTabIndex(selectedIndex);

                Const.form.boardListTabControlParts.ResumeLayout();
            }
            catch { ;}
        }

        public virtual void DispooseAll()
        {
            try
            {
                ageonMutex.Terminate();

                this.boardListControls.ResetControls();

                this.boardListControls.RemoveAllControls();

                MainFormConst.boardListTabMain.remove_view((BoardViewCommon)this);

                //this.threadInfo.threadDataList.Clear();
                //this.bvTimeExtraction.threadInfo.threadDataList.Clear();
                //this.wordExtraction.threadInfo.threadDataList.Clear();
            }
            catch { ;}
        }
        public void SelectTabIndexFirst(int selectIndex)
        {
            try
            {
                if (selectIndex == 0)
                    Const.form.boardListTabControlParts.SelectedIndex = 0;
                else if (selectIndex == 1)
                    Const.form.boardListTabControlParts.SelectedIndex = 0;
                else if (selectIndex == 2)
                    Const.form.boardListTabControlParts.SelectedIndex = 1;
                else if (selectIndex == 3)
                    Const.form.boardListTabControlParts.SelectedIndex = 2;
                else if (selectIndex == 4)
                    Const.form.boardListTabControlParts.SelectedIndex = 3;
                else if (selectIndex == 5)
                    Const.form.boardListTabControlParts.SelectedIndex = 4;
                else if (selectIndex == 6)
                    Const.form.boardListTabControlParts.SelectedIndex = 5;
                else if (selectIndex == 7)
                    Const.form.boardListTabControlParts.SelectedIndex = 6;
                else if (selectIndex == 8)
                    Const.form.boardListTabControlParts.SelectedIndex = 7;
                else if (selectIndex == 9)
                    Const.form.boardListTabControlParts.SelectedIndex = 8;
                else if (selectIndex == 10)
                    Const.form.boardListTabControlParts.SelectedIndex = 9;
                else
                    Const.form.boardListTabControlParts.SelectedIndex = selectIndex - 10;

            }
            catch { ;}
        }
        public void SelectTabIndex(int selectedIndex)
        {
            try
            {
                if (selectedIndex == Const.form.boardListTabControlParts.Count)
                    Const.form.boardListTabControlParts.SelectedIndex = selectedIndex - 1;
                //それ以外では、前の選択されていたタブを選択
                else
                    Const.form.boardListTabControlParts.SelectedIndex = selectedIndex;

                while (Const.form.boardListTabControlParts.control.SelectedTab.Text.Length == 0)
                {
                    if (Const.form.boardListTabControlParts.SelectedIndex < 1)
                        break;
                    Const.form.boardListTabControlParts.SelectedIndex -= 1;
                }
            }
            catch (System.Exception ex)
            {
                Const.debugForm.OutPutDebug("BoarddList", ex);
                return;
            }
        }

        public void worker()
        {
            try
            {
                show_board(board_url);
            }
            catch { ;}
        }

        public void Write_List_Dele()
        {
            try
            {
                this.boardListControls.listViewParts.VirtualListSize = 0;
                this.WriteList();
                boardListControls.listViewParts.VirtualListSize = boardListControls.listViewParts.itemSize;
            }
            catch { ;}

        }

        public void reload()
        {
            /* ロック */
            //if (this.ageonMutex.WaitOne() == false)
            //{
            //    this.ageonMutex.ReleaseMutex();
            //    return;
            //}

            try
            {
                Thread t = new Thread(new ThreadStart(worker));
                t.IsBackground = true;
                t.Start();
            }
            catch { ;}

                        /* ロック開放 */
            //this.ageonMutex.ReleaseMutex();
        }

        public void ShowThreadInBeginInvoke(string threadUrl, string threadName)
        {
            try
            {
                MainFormConst.threadListTabMain.ShowThread(threadUrl, threadName);
            }
            catch { ;}
        }

        public void ShowThread(string threadUrl, string threadName)
        {
            try
            {
                MainFormConst.threadListTabMain.ShowThread(threadUrl, threadName);
                return;
            }
            catch { ;}
        }

        private void ShowThreadInThread(object tp)
        {
            try
            {
                ThreadOpenParam parse = (ThreadOpenParam)tp;
                MainFormConst.threadListTabMain.ShowThread(parse.threadUrl, parse.threadName);
            }
            catch { ;}
        }

        public void WriteList()
        {
            try
            {
                this.boardListControls.listViewParts.WriteListView();
            }
            catch { ;}
        }

        public void WriteLogFile(List<ThreadData> threadList)
        {
            try
            {
                StringBuilder sb = new StringBuilder();

                foreach (ThreadData thread in threadList)
                {
                    sb.Append(SubjectUtil.MakeSubjectInfoLine(thread));
                }

                string typename = Util.BoardUrlToBoardTypeName(board_url);
                string boardid = Util.BoardUrlToBoardID(this.board_url);

                string dir = ".ageon" + Path.DirectorySeparatorChar + "cache" + Path.DirectorySeparatorChar + 
                    typename + Path.DirectorySeparatorChar + boardid;

                try
                {
                    FileIO.SaveUnicode(dir, "subject_info.txt", sb.ToString());
                }
                catch
                {
                    return;
                }
            }
            catch { ;}
        }
        public virtual ThreadInfo ReadLogFile()
        {
            try
            {
                string typename = Util.BoardUrlToBoardTypeName(board_url);
                string boardid = Util.BoardUrlToBoardID(this.board_url);

                string dir = ".ageon" + Path.DirectorySeparatorChar + "cache" + Path.DirectorySeparatorChar +
                    typename + Path.DirectorySeparatorChar + boardid;

                string data = "";

                try
                {
                    data = FileIO.ReadUnicode(dir, "subject_info.txt");
                }
                catch
                {
                    return new ThreadInfo();
                }

                try
                {
                    return SubjectUtil.ParseSubjectInfoLines(data, "subject_info.txt");
                }
                catch
                {
                    return new ThreadInfo();
                }
            }
            catch
            {
                return new ThreadInfo();
            }
        }

        //既読、未読等の情報を新しいデータに引き継ぐ
        public void CompotionList(List<ThreadData> threadList, List<ThreadData> newList)
        {
            try
            {
                if ((threadList != null) && (threadList.Count != 0))
                {
                    foreach (ThreadData newThreadInfo in newList)
                    {
                        //これまでに無いデータにnewのフラグを立てる
                        bool oldFlag = false;

                        foreach (ThreadData oldThreadInfo in threadList)
                        {
                            if (newThreadInfo.datUrl.CompareTo(oldThreadInfo.datUrl) == 0)
                            {
                                newThreadInfo.readNum = oldThreadInfo.readNum;
                                threadList.Remove(oldThreadInfo);
                                //フラグを立てる
                                oldFlag = true;
                                break;
                            }
                        }
                        //これまでに無ければNewフラグを立てる
                        if (oldFlag == false)
                            newThreadInfo.newThread = true;
                    }
                }
                else
                {
                    foreach (ThreadData newThreadInfo in newList)
                        newThreadInfo.newThread = true;
                }
            }
            catch { ;}
        }
        //ここで引数としてwithInやpinPointTimeを得る。そしてこのメソッドで書き換えなしのBoardViewExtractionのSetDataを作って実行する

        delegate void ShowToolTipDelegate(string text, ListViewParts listViewParts);

        public void show_board(string url)
        {
            /* ロック */
            if (this.ageonMutex.WaitOne() == false)
            {
                this.ageonMutex.ReleaseMutex();
                return;
            }

            try
            {   
                Const.form.mainForm.Invoke(new ShowToolTipDelegate(this.boardListControls.toolTipParts.ShowToolTip),
                this.board_url + "を読み込み中...", this.boardListControls.listViewParts);


                if (url.Length == 0)
                    return;

                this.board_url = url;

                string subjectTextUrl;
                if (url.EndsWith("php") == true)
                {
                    subjectTextUrl = url; //この形式には対応していない
                    return;
                }
                else
                    subjectTextUrl = url + "subject.txt";


                //ログがある時にここをtureにしたいこともあるが、それは別のメソッドで実装する。
                //ここはダウンロード用メソッドなのでこれで。
                this.completeDownloading = false;

                //オンラインの時の動作
                if (Const.OnLine == true)
                {
                    switch (Util.BoardType(url))
                    {
                        case Util.TYPE_2CH:
                        case Util.TYPE_MACHIBBS:
                        case Util.TYPE_UNKNOWN:
                        case Util.TYPE_2CHSC:
                        case Util.TYPE_OPEN2CH:
                        case Util.TYPE_NEXT2CH:
                        case Util.TYPE_JIKKYO:
                        case Util.TYPE_BLOGBAN:
                        case Util.TYPE_SHIZU:
                        case Util.TYPE_VIP2CH:
                            DownloadToSet(subjectTextUrl);
                            break;
                        case Util.TYPE_JBBS:
                            DownloadToSet(subjectTextUrl);
                            break;
                        case Util.TYPE_FAVORITE:
                        case Util.TYPE_SCREENING:
                            ReadToSet(url);
                            break;
                    }
                }
                //オフライン時の動作
                else
                {
                    switch (Util.BoardType(url))
                    {
                        case Util.TYPE_2CH:
                        case Util.TYPE_MACHIBBS:
                        case Util.TYPE_UNKNOWN:
                        case Util.TYPE_2CHSC:
                        case Util.TYPE_OPEN2CH:
                        case Util.TYPE_NEXT2CH:
                        case Util.TYPE_JIKKYO:
                        case Util.TYPE_BLOGBAN:
                        case Util.TYPE_SHIZU:
                        case Util.TYPE_VIP2CH:
                            ReadToSet(subjectTextUrl);
                            break;
                        case Util.TYPE_JBBS:
                            ReadToSet(subjectTextUrl);
                            break;
                        case Util.TYPE_FAVORITE:
                        case Util.TYPE_SCREENING:
                            ReadToSet(url);
                            break;
                    }
                }
            }
            catch { ;}

            Const.form.mainForm.Invoke(new Action(this.boardListControls.toolTipParts.HideToolTip));

            /* ロック開放 */
            this.ageonMutex.ReleaseMutex();
        }

        public void ReadToSet(string url)
        {
            try
            {
                this.completeDownloading = true;

                //string[] rows = url.Split(new char[] { '/' });
                
                if (threadInfo != null)
                {
                    threadInfo.threadDataList.Clear();
                    threadInfo.threadDataList = null;
                    threadInfo = null;
                }

                threadInfo = ReadLogFile();

                //if (threadInfo.threadDataList.Count <= 0)
                //    return;

                Const.form.mainForm.Invoke(new Action(Write_List_Dele));

                //threadList.Clear();
            }
            catch { ;}
        }

        public void DownloadToSet(string subjectTextUrl)
        {
            try
            {
                string str;
                DownloadSubject ds = new DownloadSubject();
                if (true == ds.DownloadSubjectText(subjectTextUrl))
                {
                    str = ds.httpResData;
                }
                else
                    return;

                if (str.Length <= 0)
                    return;

                this.completeDownloading = true;

                //設定を読み込む
                threadInfo = ReadLogFile();

                ThreadInfo newInfo = SubjectUtil.ParseSubjectLines(str, this.board_url);

                if (threadInfo != null)
                {
                    this.CompotionList(threadInfo.threadDataList, newInfo.threadDataList);
                    threadInfo.threadDataList.Clear();
                    threadInfo.threadDataList = null;
                    threadInfo = null;
                }
                threadInfo = newInfo;
                WriteLogFile(threadInfo.threadDataList);

                //時間選択が行われていれば、データを作る
                //if (bvExtraction.threadInfo != null)
                bvTimeExtraction.WriteKakoLog(threadInfo, this.board_url);

                bvTimeExtraction.MakeExtractionThreadInfo();
                ;
                Const.form.mainForm.Invoke(new Action(Write_List_Dele));
                //frontBoardListControls.listViewPart.listView.VirtualListSize = 1000;
            }
            catch { ;}
        }
    }
}
