using System;
using System.IO;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Xml;
using System.Collections;
using System.Diagnostics;

namespace カブラウザもどき
{
    /// <summary>
    /// ヤフー掲示板から情報取得を受け持つクラス
    /// Form1クラスとはcontextクラスを介して情報の受け渡しを行う
    /// ヤフー掲示板の仕様に依存する実装を行う。
    /// </summary>
    class GetYahoo
    {
        CurrentContext context = null;
        TextBox console = null;
        ToolStripStatusLabel console2 = null;
        private WebBrowserController ndbControl = null;

        public GetYahoo(カブラウザもどき.CurrentContext context, TextBox console, ToolStripStatusLabel console2, WebBrowserController ndbControl)
        {
            this.context = context;
            this.console = console;
            this.console2 = console2;
            this.ndbControl = ndbControl;
        }
        /// <summary>
        /// 表示用のURLを返す
        /// </summary>
        /// <param name="mid"></param>
        /// <returns></returns>
        public string GetMessageUrl(string mid)
        {
            return "http://messages.yahoo.co.jp/bbs?mm=FN&action=m&board=1" + context.GetPad() + context.GetCode() + "&tid=" + context.tid + "&sid=1" + context.GetPad() + context.GetCode() + "&mid=" + mid;
        }        /// <summary>
        /// 返信用のURLを返す
        /// </summary>
        /// <param name="mid"></param>
        /// <returns></returns>
        public string GetReplyUrl(string mid)
        {
            return "http://post.messages.yahoo.co.jp/bbs?mm=FN&action=r&board=1" + context.GetPad() + context.GetCode() + "&tid=" + context.tid + "&sid=1" + context.GetPad() + context.GetCode() + "&mid=" + mid;
        }
        /// <summary>
        /// スレッドで表示URLを返す
        /// </summary>
        /// <param name="mid"></param>
        /// <returns></returns>
        public string GetThreadUrl(string mid)
        {
            return "http://post.messages.yahoo.co.jp/bbs?mm=FN&action=m&board=1" + context.GetPad() + context.GetCode() + "&tid=" + context.tid + "&sid=1" + context.GetPad() + context.GetCode() + "&mid=" + mid + "&thr=" + mid + "&cur=" + mid;
        }

        public string GetHalfYearChartUrl()
        {
            return "http://stocks.finance.yahoo.co.jp/stocks/chart/?code=" + context.GetCodeAndExchange() + "&ct=z&t=6m&q=c&l=off&z=m&p=m5,m25,s&a=v";
        }
        public string GetNewsUrl()
        {
            return "http://stocks.finance.yahoo.co.jp/stocks/news/?code=" + context.GetCode();
        }
        public string GetColum()
        {
            return "http://news.finance.yahoo.co.jp/search/?q=" + context.GetCode();
        }
        public string GetCompanyInfo()
        {
            return "http://stocks.finance.yahoo.co.jp/stocks/profile/?code=" + context.GetCode();
        }
        public string GetDailyRankingUrl()
        {
            return "http://messages.yahoo.co.jp/ranking/stocks/postranking_daily.html";
        }
        public string GetWeeklyRankingUrl()
        {
            return "http://messages.yahoo.co.jp/ranking/stocks/postranking_weekly.html";
        }
        public string GetMonthlyRankingUrl()
        {
            return "http://messages.yahoo.co.jp/ranking/stocks/postranking_monthly.html";
        }
        public string GetBaseMessageUrl()
        {
            return "http://messages.yahoo.co.jp/bbs?.mm=FN&action=m&board=1" + context.GetPad() + context.GetCode() + "&tid=" + context.tid + "&sid=1" + context.GetPad() + context.GetCode() + "&mid=";
        }
        public string GetMassageUrl(string mid)
        {
            return "http://messages.yahoo.co.jp/bbs?.mm=FN&action=m&board=1" + context.GetPad() + context.GetCode() + "&tid=" + context.tid + "&sid=1" + context.GetPad() + context.GetCode() + "&mid=" + mid;
        }
        /// <summary>
        /// 自分の投稿
        /// </summary>
        /// <returns></returns>
        public string GetPostedSelf() {
            return "http://messages.yahoo.co.jp/my.html";
        }
        public bool IsValidYahooCode(string code)
        {
            bool ret = false;
            string chkUrl = "http://m.finance.yahoo.co.jp/stock/bbs?code=" + code;

            HtmlDocument doc = null;
            NonDispBrowser ndb2 = new NonDispBrowser();

            try {
                ndb2.NavigateAndWait(chkUrl);
                doc = ndb2.Document;

                // エラーチェック
                if (doc.Title.ToString() == "エラー - Y!ファイナンス") {

                    console.AppendText("( ・益・)ﾉ > そんなもんねぇよ。　 " + code + Form1.csCrLf);

                } else {

                    // 会社名を解析
                    string companyName = doc.Title.ToString();
                    context.comapnyName = companyName.Split('【')[0];
                    console.AppendText(doc.Title.ToString() + Form1.csCrLf);

                    string sLink = "";
                    HtmlElementCollection el = doc.GetElementsByTagName("A");
                    foreach ( HtmlElement e in el ) {
                        sLink = e.GetAttribute("href");
                        context.SetCode(code);
                        if ( sLink.ToString() == "http://m.finance.yahoo.co.jp/stock?code=" + context.GetCode() + ".T" || 
                            sLink.ToString() == "http://m.finance.yahoo.co.jp/stock?code=" + context.GetCode() + ".O" || 
                            sLink.ToString() == "http://m.finance.yahoo.co.jp/stock?code=" + context.GetCode() + ".Q" ) {
                            context.SetCodeAndExchange(e.GetAttribute("href").Replace("http://m.finance.yahoo.co.jp/stock?code=", ""));
                        }
                    }

                    ret = true;
                }
            }
            finally {
                ndb2.Dispose();
                ndb2 = null;
            }
            return ret;
        }

        /// <summary>
        /// チャートのhtmlを取得する
        /// </summary>
        /// <returns></returns>
        public string GetChartHtml(WebBrowser webBrowser1)
        {
            string ret = "";
            if (webBrowser1.Version.Major > 6) {
                ret = "<style type='text/css'>TD.y_chart { font-size: 12px; background: #EEEEDD; border: 1px; }</style>";
                ret += "<br><table border='1' cellspacing='0'><tr>";
                ret += "<td class='y_chart'>日足</td><td class='y_chart'>1週間</td></tr><tr>";
                ret += "<td rowspan='3'><img src='http://rchart.yahoo.co.jp/z?s=" + context.GetCodeAndExchange() + "&t=6m&l=off&z=m&q=c&a=v&c=' width='400'></img>";
                ret += "</td><td rowspan='1'>";
                ret += "<img src='http://rchart.yahoo.co.jp/g?s=" + context.GetCodeAndExchange() + "&t=6m&l=off&z=m&q=c&a=v&c=' width='200'></img>";
                ret += "</tr><tr><td class='y_chart'>日中足</td></tr><tr><td rowspan='1'>";
                ret += "<img src='http://rchart.yahoo.co.jp/f?s=" + context.GetCodeAndExchange() + "&t=6m&l=off&z=m&q=c&a=v&c=' width='200'></img>";
                ret += "</td></tr></table>";
            } else  // IE6以下はアンチエイリアスが効かなくて汚い
            {
                ret = "<style type='text/css'>TD.y_chart { font-size: 12px; background: #EEEEDD; border: 1px; }</style>";
                ret += "<br><table border='1' cellspacing='0'><tr>";
                ret += "<td class='y_chart'>日足</td><td class='y_chart'>1週間</td></tr><tr>";
                ret += "<td rowspan='3'><img src='http://rchart.yahoo.co.jp/z?s=" + context.GetCodeAndExchange() + "&t=6m&l=off&z=m&q=c&a=v&c='></img>";
                ret += "</td><td rowspan='1'>";
                ret += "<img src='http://rchart.yahoo.co.jp/g?s=" + context.GetCodeAndExchange() + "&t=6m&l=off&z=m&q=c&a=v&c=' ></img>";
                ret += "</tr><tr><td class='y_chart'>日中足</td></tr><tr><td rowspan='1'>";
                ret += "<img src='http://rchart.yahoo.co.jp/f?s=" + context.GetCodeAndExchange() + "&t=6m&l=off&z=m&q=c&a=v&c=' ></img>";
                ret += "</td></tr></table>";
            }
            return ret;
        }

        /// <summary>
        /// 投稿タイトル一覧をRSSから取得して配列に格納する
        /// 取得は高速だが、最新しか取得できない。前の頁以前は取得不可。
        /// GetTitleListsFromHtmlを使用する事。
        /// </summary>
        /// <param name="longCode"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public int GetTitleListsFromRSS(string longCode )
        {
            if (longCode == "") { return -1; }
            string code = longCode.Substring(0, 4);
            context.SetCode(code);
            GetTopicId(code, true);
            TitleLists [] t = context.t;
            NonDispBrowser ndb = (NonDispBrowser)ndbControl.GetBrowser();

            // RSSフィードURLを取得する
            string chkUrl = "http://messages.yahoo.co.jp/bbs?action=topics&board=1" + context.GetPad() + code + "&sid=1" + context.GetPad() + code + "";
            string rssUrl = "http://messages.yahoo.co.jp/bbs?action=4&board=1" + context.GetPad() + code + "&sid=1" + context.GetPad() + code + "&tid=" + code;
            ndb.NavigateAndWait(chkUrl);
            HtmlDocument doc = ndb.Document;
            context.title = doc.Title;

            bool breakFlag = false;
            //
            // TopicIdを取得する
            foreach (HtmlElement e in doc.GetElementsByTagName("LINK")) {
                string text = e.OuterHtml.Replace("&amp;", "&"); // リンク文字列
                string[] aTmp;
                if (text.IndexOf("rel=alternate") != -1) {
                    aTmp = text.Split('&');
                    foreach (string s in aTmp) {
                        if (s.Length > 3 && s.Substring(0, 3) == "tid") {
                            string regularTid = s.Split('=')[1];
                            regularTid = regularTid.Split('"')[0];
                            context.tid = regularTid;
                            rssUrl = "http://messages.yahoo.co.jp/bbs?action=4&board=1" + context.GetPad() + code + "&sid=1" + context.GetPad() + code + "&tid=" + context.tid;
                            breakFlag = true;
                        }
                        if (breakFlag) break;
                    }

                }
                if (breakFlag) break;
            }
            // ndb = null;
            console.AppendText("( ･∀･)ﾉ > げっと！　 " + code + Form1.csCrLf);

            // タイトル一覧取得
            XmlDocument xmlDoc = new XmlDocument();
            try {
                xmlDoc.Load(rssUrl);
            }
            catch (XmlException e) {
                console.AppendText("　( ・益・)　ﾉ > そんなもん、ねぇよ　 " + Form1.csCrLf);
                return -1;
            }
            context.ClearTitleList();
            XmlNodeList nodes = xmlDoc.GetElementsByTagName("item");

            string[] aUrl;
            for (int i = 0; i < nodes.Count; i++) {
                XmlNodeList titleNodes = nodes[i].SelectNodes("title");
                XmlNodeList dateNodes = nodes[i].SelectNodes("pubDate");
                XmlNodeList linkNodes = nodes[i].SelectNodes("link");
                XmlNodeList descNodes = nodes[i].SelectNodes("description");

                context.t[i].title = titleNodes[0].InnerText;
                context.t[i].sendTime = dateNodes[0].InnerText;
                context.t[i].url = linkNodes[0].InnerText;

                aUrl = descNodes[0].InnerText.Split(',');
                for (int j = 0; j < aUrl.Length; j++) {
                    if (aUrl[j].Length > 4 && aUrl[j].Substring(0, 4) == "投稿者:") context.t[i].sender = aUrl[j].Replace("投稿者:", "");
                    if (aUrl[j].Length > 5 && aUrl[j].Substring(0, 5) == "投稿番号:") context.t[i].titleNo = aUrl[j].Replace("投稿番号:", "");
                    if (aUrl[j].Length > 5 && aUrl[j].Substring(0, 5) == "投稿日時:") context.t[i].sendTime = aUrl[j].Replace("投稿日時:", "");
                }

                if (aUrl.Length == 5) {
                    context.t[i].emotion = aUrl[4];
                }

                //                context.ht[context.t[i].titleNo] = context.t[i];
            }
            context.SetCode(code);
            context.maxTilteNo = context.t[0].titleNo;
            // context.Save();
            return 0;
        }

        /// <summary>
        ///  Yahoo掲示板のTopic ID (tid=部分)、最大TitleNo を取得する.取得値は状態変数に格納する
        /// </summary>
        /// <returns></returns>
        public int GetTopicId(string code, bool isCheckLock)
        {
            int ret = 0;         // 戻り値
            int iMaxTitleNo = 0; // 最大タイトルNo
            string sComp = "";   // タイトルNo比較用
            bool breakFlag = false;
            bool titleFlag = false;
            NonDispBrowser ndb = (NonDispBrowser)ndbControl.GetBrowser();

            context.SetCode(code);
            string chkUrl = "http://messages.yahoo.co.jp/bbs?action=topics&board=1" + context.GetPad() + context.GetCode() + "&sid=1" + context.GetPad() + context.GetCode() + "";

            if (!ndb.NavigateAndWait(chkUrl)) {
                console.AppendText("（｡・-・）失敗ｼﾀﾖｳﾀﾞ...もう一回やって！" + Form1.csCrLf);
            }

            HtmlDocument doc = ndb.Document;

            // object lcok
            if (isCheckLock) {
                if (!context.Lock()) { MessageBox.Show("銘柄コードは現在ロックされています\nしばらくお待ちください"); return -1; }
            }
            // object lock

            try {
                // Topic id取得
                foreach (HtmlElement e in doc.GetElementsByTagName("LINK")) {
                    string text = e.OuterHtml.Replace("&amp;", "&"); // リンク文字列
                    string[] aTmp;
                    if (text.IndexOf("rel=alternate") != -1) {
                        aTmp = text.Split('&');
                        foreach (string s in aTmp) {
                            if (s.Length > 3 && s.Substring(0, 3) == "tid") {
                                string regularTid = s.Split('=')[1];
                                regularTid = regularTid.Split('"')[0];
                                context.tid = regularTid;
                                breakFlag = true;
                            }
                            if (breakFlag) break;
                        }

                    }
                    if (breakFlag) break;
                }

                // 最大TitleNo取得
                foreach (HtmlElement e in doc.GetElementsByTagName("A")) {
                    string sLink = e.GetAttribute("href");

                    if (sLink.Length > 33 && sLink.Substring(0, 33) == "http://post.messages.yahoo.co.jp/") context.postUrl = sLink.ToString();

                    if (sLink.Length > 50 && sLink.Substring(0, 47) == "http://messages.yahoo.co.jp/bbs?.mm=FN&action=m") {
                        string[] de = { "mid=", "\">" };
                        string[] tmp = e.OuterHtml.Split(de, StringSplitOptions.None);
                        if (tmp.Length > 1) {
                            sComp = tmp[1];
                            int test = 0;
                            if (int.TryParse(sComp, out test)) {
                                if (iMaxTitleNo < test) {
                                    iMaxTitleNo = test;
                                }
                            }
                        }
                    }
                }
                // IMG用の市場コードを含んだ銘柄コード
                foreach (HtmlElement e in doc.GetElementsByTagName("IMG")) {
                    string sLink = e.GetAttribute("src");
                    try {
                        if (sLink.Length >= 36 && (sLink.Substring(0, 30) == "http://rchart.yahoo.co.jp/t?s=" || sLink.Substring(0, 30) == "http://rchart.yahoo.co.jp/t?s=")) {
                            string tmp = sLink.ToString().Substring(30, sLink.Length - 30);
                            context.SetCodeAndExchange(tmp.Split('&')[0]);
                        }
                    }
                    catch (NullReferenceException exp) {
                        context.SetCodeAndExchange("");
                    }
                }

                context.maxTilteNo = iMaxTitleNo.ToString();
                if (context.maxTilteNo == "") titleFlag = false; else titleFlag = true;

                //終値と前日比
                foreach (HtmlElement e in doc.GetElementsByTagName("DIV")) {
                    switch (e.GetAttribute("className")) {
                        case "kabu_meigara":
                            context.title = e.InnerText;
                            if (e.GetElementsByTagName("A").Count > 0) {
                                context.comapnyName = e.GetElementsByTagName("A")[0].InnerText;
                            }
                            break;
                        case "kabu_date":
                            context.GetSkin().set("&DATE", e.InnerHtml);
                            break;
                        case "kabu_number_price":
                            context.GetSkin().set("&CLOSE", e.InnerHtml);
                            context.close = e.InnerText;
                            break;
                        case "kabu_number_change":
                            context.GetSkin().set("&CHANGE", e.InnerHtml);
                            context.change = e.InnerText;
                            break;
                        default:
                            break;

                    }
                }

            }
            catch (IndexOutOfRangeException e) {
                console.AppendText(e.ToString() + Form1.csCrLf);
                context.maxTilteNo = "";
                ret = -1;
            }
            catch (NullReferenceException e) {
                console.AppendText(e.ToString() + Form1.csCrLf);
                context.maxTilteNo = "";
                ret = -1;
            }
            finally {
                if (isCheckLock) {
                    context.UnLock();
                }
                ret = (titleFlag && breakFlag) ? 0 : -1;
            }

            //context.maxTilteNo = maxTitleNo.ToString();
            return ret;
        }

        /// <summary>
        /// 引数のURLのメッセージコンテンツを取得する 
        /// URL例) http://messages.yahoo.co.jp/bbs?.mm=FN&action=m&board=1005214&tid=ffckdcee5a4bekbbr&sid=1005214&mid=10331
        /// </summary>
        /// <param name="mid"></param>
        /// <returns></returns>
        public string GetContentsFromPCSite(string mid)
        {
            // 画像、ActiveXのダウンロードを抑止
            //WebBrowserController ctl = new WebBrowserController(this.webBrowser1);
            ComConstants now = ndbControl.DlControl;
            ComConstants filter = ComConstants.DLCTL_NO_DLACTIVEXCTLS
                                | ComConstants.DLCTL_NO_JAVA
                                | ComConstants.DLCTL_NO_SCRIPTS
                                | ComConstants.DLCTL_NO_DLACTIVEXCTLS
                                | ComConstants.DLCTL_NO_RUNACTIVEXCTLS
                                & ~ComConstants.DLCTL_DLIMAGES;
            ndbControl.DlControl = filter;
            NonDispBrowser ndb = (NonDispBrowser)ndbControl.GetBrowser();
            try {
                // メッセージ内容はhtmlの中から"class=s130"をキーとして取得する
                string pad = "";
                string url = GetMassageUrl(mid);
                //toolStripStatusLabel1.Text = url;

                //DL時間計測
                Stopwatch watch = new Stopwatch();
                watch.Start();
                if (!ndb.NavigateAndWait(url)) {
                    console.AppendText("（｡・-・）失敗ｼﾀﾖｳﾀﾞ...もう一回やって！" + Form1.csCrLf);
                }
                HtmlDocument doc = ndb.Document;
                if (doc.Title == "Yahoo!掲示板 - エラー") return doc.Title;
                context.title = doc.Title;

                watch.Stop();
                //this.textBox2.AppendText("計測時間: " + watch.ElapsedMilliseconds + csCrLf);

                // コンテンツの取得方法１ (skin利用時はこれを採用)
                HtmlElementCollection all = doc.All;
                HtmlElementCollection ec = doc.GetElementsByTagName("TD");
                YahooSkin skin = context.GetSkin();
                skin.ContextToSkin(context);
                foreach (HtmlElement e in ec) {
                    switch (e.GetAttribute("className")) {
                        case "s130":
                            //skinファイルに内容を格納
                            skin.set("&MESSAGE", e.InnerHtml);
                            skin.set("&RESURL",
                                "http://post.messages.yahoo.co.jp/bbs?mm=FN&action=r&board=1" + context.GetPad() + context.GetCode() + "&tid=" + context.tid + "&sid=1" + context.GetPad() + context.GetCode() + "&mid=" + mid);
                            // titlelistからskin変数格納
                            //foreach (ListViewItem item in this.listView1.Items) {
                            foreach ( TitleLists item in context.t ) {
                                if (mid == item.titleNo) {
                                    skin.set("&NUMBER", item.titleNo);
                                    skin.set("&TITLE", item.title);
                                    skin.set("&NAME", item.sender);
                                    skin.set("&FEELINGS", item.emotion);
                                    skin.set("&DATE", item.sendTime);
                                }
                            }
                            break;
                        default:
                            break;

                    }

                }

                ec = doc.GetElementsByTagName("A");
                foreach (HtmlElement e in ec) {
                    switch (e.GetAttribute("className")) {

                        case "findMessage":
                            skin.set("&M_FINDMSG", e.GetAttribute("HREF"));
                            skin.set("&M_NICKNAME", e.GetAttribute("HREF").Replace("http://search.messages.yahoo.co.jp/search/?p=", ""));
                            break;
                        default:
                            break;

                    }
                }
                // コンテンツの取得方法２　早いが失敗する可能性あり
                /*  skin対応前はこれを使用する
                try
                {
                    string retHtml = "";
                    if (doc.GetElementsByTagName("TABLE").Count >= 25)
                    {
                        HtmlElement eRet = doc.GetElementsByTagName("TABLE")[25];
                        retHtml = eRet.OuterHtml;
                        eRet = null;
                        doc = null;
                    }
                    else retHtml = "contents get error!";
                    return retHtml;
                }
                catch (NullReferenceException e)
                {
                    Console.WriteLine(e.ToString());
                    return "contents get error!";
                }
                */
                /**
                // コンテンツの取得方法３
                // 遅い
                HtmlElementCollection ec2 = doc.GetElementsByTagName("TABLE");
                int i = 0;
                foreach (HtmlElement e in ec2)
                {
                    if (e.OuterHtml.IndexOf("class=s130") != -1)
                    {
                        i++;
                        if (i == 3)
                        {
                            string retHtml = e.OuterHtml;
                            e = null;
                            ec2 = null;
                            ndb = null;
                            return retHtml;
                        }
                    }
                }
                **/
            }
            catch (NullReferenceException e) {

                console.AppendText(e.ToString() + Form1.csCrLf);
            }
            finally {
                ndbControl.DlControl = now;
            }

            return "contents get error!";
        }

        /// <summary>
        /// 引数のURLのメッセージコンテンツをYahooモバイルから取得する 
        /// 例) http://m.finance.yahoo.co.jp/stock/bbs?code=6255
        /// </summary>
        /// <param name="mid"></param>
        /// <returns></returns>
        private string GetContentsFromMobileSite(string mid)
        {
            NonDispBrowser ndb = (NonDispBrowser)ndbControl.GetBrowser();

            try {
                // メッセージ内容はhtmlの中から"class=s130"をキーとして取得する
                string url = "http://m.finance.yahoo.co.jp/stock/bbs?code=" + context.GetCode();
                // toolStripStatusLabel1.Text = url;
                ndb.NavigateAndWait(url);

                bool bThisMessage = false;

                HtmlDocument doc = ndb.Document;
                HtmlElementCollection all = doc.All;
                HtmlElementCollection articles = doc.GetElementsByTagName("article");
                HtmlElementCollection titles = doc.GetElementsByTagName("h3");
                HtmlElementCollection texts = doc.GetElementsByTagName("p");

                Console.WriteLine("message id: " + mid);

                for (int i = 0; i < all.Count; i++) {
                    if (all[i].GetAttribute("classname") == "title" && (all[i].InnerText.IndexOf(mid) != -1)) {
                        for (int j = 0; j < 10; j++) {
                            Console.WriteLine(all[i + j].InnerText);
                            if (all[i + j].GetAttribute("classname") == "text") {
                                return all[i + j].InnerText;
                            }
                        }
                    }
                }

                for (int i = 0; i < titles.Count; i++) {
                    if (titles[i].InnerText.IndexOf(mid) != -1) {
                        return articles[i].InnerHtml;
                    }
                }

                // 引数のmidのメッセージを探し出して戻す
                foreach (HtmlElement article in articles) {
                    //                foreach (HtmlElement e in article)
                    //                {
                    HtmlElement e = article;
                    if (e.GetAttribute("className") == "title") {
                        if (e.InnerText.IndexOf(mid) != -1) {
                            bThisMessage = true;
                        };
                    }
                    if (e.GetAttribute("className") == "text" && bThisMessage == true) {
                        if (e.InnerText.IndexOf(mid) != -1) {
                            return e.InnerHtml;
                        };
                    }
                    //                }
                }
            }
            finally {
            }
            return "contents get error!";
        }


        ///<summary>
        /// HTMLから投稿タイトル一覧を全部取得してファイルに保存する
        /// 最新titleIDからmaxRow分はTitleListsクラスに格納する
        ///</summary>
        public int SaveAllTitleList(string code, ref TitleLists[] t)
        {
            int maxTitleNo = 0;  // 取得済みのtitle

            if (code == "") { return -1; }
            
            NonDispBrowser ndb = (NonDispBrowser)ndbControl.GetBrowser();
            bool bReadExitFlag = false; // キャッシュされた最新まで達したので読込み終了する

            if ((MessageBox.Show("この処理を行うとタイトルによる「全文検索」が可能となりますが、\n処理は５分から１０分程度の時間がかかります。続行しますか？", "ダウンロード確認",
                    MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No)) { return -1; }

            if (File.Exists(Form1.csDatDir + code + ".dat")) {
                string line = "";
                using (StreamReader sr = new StreamReader(Form1.csDatDir + code + ".dat")) {
                    line = sr.ReadLine();
                    if (line != null && line.Split(Form1.delimiter).Length > 1) {
                        maxTitleNo = int.Parse(line.Split(Form1.delimiter)[0]);
                        MessageBox.Show(maxTitleNo + "以降を取得して保存します。");
                    }
                }
            }

            if (!context.Lock()) { MessageBox.Show("銘柄コードは現在ロックされています\nしばらくお待ちください"); return -1; }
            try {
                //string code = longCode.Substring(0, 4);

                int chk = GetTopicId(code, false);

                if (chk == 0) {

                    TitleLists data = new TitleLists();

                    // 最新の一覧
                    ndb.NavigateAndWait("http://messages.yahoo.co.jp/bbs?action=topics&board=1" + context.GetPad() + code + "&sid=1" + context.GetPad() + code + "&tid=" + context.tid);
                    string path = Form1.csDatDir + code + ".dat";

                    //if (File.Exists(path))
                    //{
                    //    SortUniqTitleList(path);
                    //}

                    StreamWriter sw = new StreamWriter(path, true);
                    sw.WriteLine("0" + Form1.delimiter + context.tid);

                    for (int i = 0; i <= (context.GetMaxTitleNo() / 40); i++) {
                        //                    Console.WriteLine(ndb.Url.ToString());
                        console2.Text = ndb.Url.ToString();
                        HtmlDocument doc = ndb.Document;

                        foreach (HtmlElement e in doc.GetElementsByTagName("A")) {
                            if (e.InnerText == "前の40件") context.prevPage = e.GetAttribute("href");
                            if (e.InnerText == "次の40件") context.nextPage = e.GetAttribute("href");
                        }

                        // 前の40件リンクを辿ってyahoo掲示板をクロール
                        // タイトル一覧はHTMLの四重にネストされたテーブル配下にある.
                        int tblCnt = 0;
                        foreach (HtmlElement e in doc.GetElementsByTagName("TABLE")) {
                            if (e.InnerText != null && e.InnerText.IndexOf("投稿時間") != -1) {
                                tblCnt++;
                                if (tblCnt == 4) {
                                    HtmlElementCollection rows = e.GetElementsByTagName("TR");
                                    foreach (HtmlElement row in rows) {
                                        HtmlElementCollection cols = row.GetElementsByTagName("TD");
                                        int chkelm = 0;
                                        bool bChk = int.TryParse(cols[0].InnerText, out chkelm);
                                        if (cols.Count == 9 && bChk && chkelm > 1 && chkelm <= context.GetMaxTitleNo()) {
                                            data.titleNo = chkelm.ToString();
                                            data.title = cols[1].InnerText;
                                            data.sender = cols[4].InnerText;
                                            data.emotion = cols[5].InnerText;
                                            data.sendTime = cols[8].InnerText;
                                            data.WriteLine(sw);
                                            if (chkelm <= maxTitleNo) {
                                                bReadExitFlag = true;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                            if (bReadExitFlag) break;
                        }
                        if (bReadExitFlag) break;
                        ndb.NavigateAndWait(context.prevPage);
                    } // 読込みループ終了
                    sw.Close();
                    sw = null;
                    SortUniqTitleList(path);
                }

            }
            finally {
                context.UnLock();
            }
            MessageBox.Show("ダウンロード完了！");
            return 0;
        }

        /// <summary>
        /// xxxx.datファイルを重複を除いて、降順にソートする
        /// </summary>
        /// <param name="path"></param>
        private void SortUniqTitleList(string path)
        {

            IDictionary dic = new Dictionary<int, string>();
            List<KeyValuePair<int, string>> list;
            // 保存したメッセージ一覧をsort & uniqする
            using (StreamReader sr = new StreamReader(path)) {
                StringReader tmp = new StringReader(sr.ReadToEnd());

                string[] splittedline;
                sr.Close();
                string line;
                while ((line = tmp.ReadLine()) != null) {
                    splittedline = line.Split(Form1.delimiter);
                    dic[int.Parse(splittedline[0])] = line;
                }

                list = SortByKey((Dictionary<int, string>)dic);

                StreamWriter sw = new StreamWriter(path);
                sw.Write("");
                foreach (KeyValuePair<int, string> tmpLine in list) {
                    sw.WriteLine(tmpLine.Value);
                }
                sw.Close();
                return;
            }
        }

        /// <summary>
        /// 連想配列のリストをキーでソートする
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        private List<KeyValuePair<int, string>> SortByKey(Dictionary<int, string> dic)
        {
            List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>(dic);
            list.Sort(
              delegate(KeyValuePair<int, string> kvp1, KeyValuePair<int, string> kvp2)
              {
                  return kvp2.Key - kvp1.Key;
              });
            return list;
        }
    
    }
}
