/*
 *  Copyright 2007 hkrn <hikarin@users.sourceforge.jp>
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 * Img0ch.App.Search
 * $Id: search.js 750 2007-06-01 13:56:04Z hikarin $
 *
 * @require jquery.js
 * @require domLib.js
 * @require domTT.js
 * @require img0ch/template/*.js
 * @require img0ch/util.js
 */

var Img0ch;
if ( typeof Img0ch == "undefined" ) Img0ch = {};
if ( typeof Img0ch.App == "undefined" ) Img0ch.App = {};
if ( typeof Img0ch.App.Read == "undefined" ) Img0ch.App.Read = {};

Img0ch.App.Search = function(option) {
    var baseURL  = option.URL;
    var bbs      = option.bbs;
    var cushion  = option.cushion || "http://nun.nu/";
    var opt      = option.option;
    var rootNode = option.rootNode || "threadRoot";
    var bbsURL   = baseURL + '/'    + bbs + '/';

    var baseURL_ = baseURL;
    var bbsURL_  = bbsURL;
    var bbs_     = bbs;
    var cgiuri_  = baseURL + "/test";
    var plugin_  = Img0ch.App.Read.Plugin;
    var plgLoad_ = false;
    var query_   = option.query;
    var static_  = option.staticURI;
    var util_    = Img0ch.Util;

    var pluginParam = query_["plugin"];
    var plugin = (typeof pluginParam == "string"
        ? pluginParam.split(',') : pluginParam || []);

    var lastUpdate_    = new Date();
    var linkRegex_     = new RegExp(
        "(https?://[A-Za-z0-9~/._\\?&=\\-%#\\+:;,@']+)", "g" );
    var linkReplaceTo_ = "<a href='" + cushion + "$1'>$1</a>";
    var option_        = opt;
    var popRegex_      = new RegExp(
        "(<a[^>]*>)?(&gt;|&gt;&gt;|＞|＞＞)([\\d\\-]+)(</a[^>]*>)?", "g" );
    var popReplaceTo_  = "<a href='javascript:void(0)' "
        + "onmouseover='" + ( option.varName || "app" )
        + ".popup( this, event, \"$3\" )'>&gt;&gt;$3</a>";
    var renderCB_      = option.renderCallback;
    var res_           = [ [ "", "", "", "", "" ] ];
    var rootNode_      = rootNode;
    var rscount_       = jQuery("span#resultCount");
    var subjectTxtURL_ = bbsURL_ + "subject.txt";
    var subjectCache_  = {};
    var template_      =
        Img0ch.Template[option.template] || Img0ch.Template.Default;
    var threadCaches_  = {};
    var lastModified_  = {};

    return {
    "getAll": function(key) {
        return threadCaches_[key + ".dat"];
    },
    "sendQuery": function(word) {
        jQuery("div#searchResultContainer").show();
        jQuery("div#searchResult").empty();
        jQuery("span#query").html(word);
        rscount_.text(String(0));
        if (!plgLoad_) {
            var pluginParam = query_["plugin"];
            var plugin = (typeof pluginParam == "string"
                ? pluginParam.split(',') : pluginParam || []);
            for ( var i in plugin ) {
                var p = plugin[i];
                this.require("img0ch/app/read/plugin/" + p + ".js");
            }
            plgLoad_ = true;
        }
        this.loadSubject(word);
        return;
    },
    "loadSubject": function(word) {
        var img0chSearch = this;
        jQuery("span#process").html("(subject.txtを読み込み中...)");
        jQuery.getIfModified( subjectTxtURL_, function(content) {
            var cache = img0chSearch.getSubjectCache();
            if (content) {
                var line  = content.split("\n");
                for ( i in line ) {
                    var subject = String(line[i]).split("<>");
                    var thread  = subject[0];
                    if (/^\d+\.dat$/.test(thread)) cache[thread] = true;
                }
            }
            var i = 1;
            for ( var thread in cache ) {
               img0chSearch.loadThread( thread, word, i );
               i++;
            }
            });
    },
    "loadThread": function( thread, word, offset ) {
        var img0chSearch = this;
        var request = bbsURL_ + "dat/" + thread + ".utf8";
        var key = String(thread).split(".")[0];
        var process = jQuery(
            "span#process").html("(" + thread + "を読み込み中...)");
        jQuery.getIfModified( request, function(content) {
            var cache = img0chSearch.getThreadCaches();
            var dat;
            if (content) {
                var line = content.split("\n");
                dat = [];
                for ( var i in line ) {
                    dat.push(String(line[i]).split("<>"));
                }
                cache[thread] = dat;
            }
            else {
                dat = cache[thread];
            }
            if (word) {
                var found  = img0chSearch.executeFromThread(
                    dat, key, word, offset );
                var before = util_.intval(rscount_.text());
                rscount_.text(String(found + before));
            }
            process.html("");
            });
    },
    "executeFromThread": function( thread, key, word, offset ) {
        var found = 0;
        var divThread = jQuery(document.createElement("div")
            ).addClass("body").addClass("thread_body"
            ).attr({ "id": "t_" + key }).get(0);
        var template  = template_;
        var util   = util_;
        var type   = util.intval(jQuery("select#searchType").val());
        var words  = util.escapeHTMLEntities(word).split(/\s+/);
        var wlen   = words.length;
        if (type > 3) type = 3;
        for ( var i in thread ) {
            var res = thread[i];
            if ( typeof res[3] == "undefined" ) continue;
            var hit    = 0;
            var result = [ res[0], res[1], res[2], res[3] ];
            var src    = res[type];
            for ( var j in words ) {
                var w = words[j];
                if ( src.indexOf(w) >= 0 ) {
                    var regex   = new RegExp(w, 'g');
                    var colored = "<b class='yellow'>" + w + "</b>";
                    src = src.replace( regex, colored );
                    hit++;
                }
            }
            if ( hit === wlen ) {
                found++;
                result[type] = src;
                template.renderRes( this, divThread, Number(i) + 1, result );
            }
        }

        if (found) {
            var threadSubject = String(thread[0][4]);
            var h2ThreadHeader = jQuery(document.createElement("h2")
                ).addClass("thread_header");
            var spanThreadInfo = jQuery(document.createElement("span")
                ).addClass("thread_info").html(
               "【" + String(offset) + ":" + thread.length + "】");
            var spanThreadSubject = jQuery(document.createElement("span")
                ).addClass("thread_subject").html(threadSubject);
            var spanDate = jQuery(document.createElement("span")
                ).addClass("date");
            spanThreadInfo.appendTo(spanDate);
            spanThreadSubject.appendTo(spanDate);
            spanDate.appendTo(h2ThreadHeader);
            var divDay = jQuery(document.createElement("div")
                ).addClass("day").attr({ "id": "t_" + key });
            h2ThreadHeader.appendTo(divDay);
            jQuery(divThread).appendTo(divDay);
            var root = document.getElementById("searchResult");
            root.appendChild(divDay.get(0));
        }
        return found;
    },
    "rewrite": function( resno, comment ) {
        comment = String(comment).replace(
            popRegex_, popReplaceTo_ )
            .replace( linkRegex_, linkReplaceTo_);
        for ( var i in plugin_ ) {
            comment = plugin_[i].rewrite( resno, comment );
        }
        return comment;
    },
    "getSubjectCache": function() {
        return subjectCache_;
    },
    "getThreadCaches": function() {
        return threadCaches_;
    },
    "getBaseURL": function() {
        return baseURL_;
    },
    "getBBSURL": function() {
        return bbsURL_;
    },
    "getBBS": function() {
        return bbs_;
    },
    "getKey": function() {
        return 0;
    },
    "getCGIURI": function() {
        return cgiuri_;
    },
    "getQuery": function() {
        return query_;
    },
    "require": function(path) {
        if (!path || !/^[\w\\/]+\w+\.js$/.test(path)) return;
        util_.require(static_ + "/js/" + path);
    }
    };
}

Img0ch.App.Read.Plugin = {};
