/**
 * Search Engine Keyword Highlight.
 *
 * This module can be imported by any HTML page, and it would analyse the
 * referrer for search engine keywords, and then highlight those keywords on
 * the page, by wrapping them around <span class="hilite">...</span> tags.
 * Document can then define styles else where to provide visual feedbacks.
 *
 * Usage:
 *
 *   In HTML. Add the following line towards the end of the document.
 *
 *     <script type="text/javascript" src="se_hilite.js"></script>
 *
 *   In CSS, define the following style:
 *
 *     .hilite { background-color: #ff0; }
 *
 *   If Hilite.style_name_suffix is true, then define the follow styles:
 *
 *     .hilite1 { background-color: #ff0; }
 *     .hilite2 { background-color: #f0f; }
 *     .hilite3 { background-color: #0ff; }
 *     .hilite4 ...
 *
 * @author Scott Yang <http://scott.yang.id.au/>
 * @version 1.2
 */

// Configuration:
Hilite = {
    /**
     * Whether we are matching an exact word. For example, searching for
     * "highlight" will only match "highlight" but not "highlighting" if exact
     * is set to true.
     */
    //exact: true,
    exact: false,

    /**
     * Whether to automatically hilite a section of the HTML document, by
     * binding the "Hilite.hilite()" to window.onload() event. If this
     * attribute is set to false, you can still manually trigger the hilite by
     * calling Hilite.hilite() in Javascript after document has been fully
     * loaded.
     */
    onload: true,

    /**
     * Name of the style to be used. Default to 'hilite'.
     */
    style_name: 'hilite',
    
    /**
     * Whether to use different style names for different search keywords by
     * appending a number starting from 1, i.e. hilite1, hilite2, etc.
     */
    style_name_suffix: true,
    //style_name_suffix: false,

    /**
     * Set it to override the document.referrer string. Used for debugging
     * only.
     */
    debug_referrer: ''
};

/**
 * Decode the referrer string and return a list of search keywords.
 */
Hilite.decodeReferrer = function(referrer) {
    var data = new Array();
    var j = jQuery.noConflict();

    var ss1 = document.getElementsByTagName("script");
    var ss2 = new Array();

    var dic_dir = '/dictionary/word/';

    for (var i = 0; i < ss1.length; i++) {
      var s = ss1[i];
      if (s.src && s.src.match(/autolink\.js(\#.*)?$/)) ss2.push(s);
    }

    for (var i = 0; i < ss2.length; i++) {
      var s = ss2[i];
      //for FireFox
      asin = s.src.replace(/http\:\/\/(.*)\/js\/autolink\.js\#/, '');
      // for IE
      asin = asin.replace(/\.\/autolink\.js\#/, '');
      asin = asin.replace(/\/js\/autolink\.js\#/, '');
    }

    if( document.URL.match('/.*\/dictionary\/.*/')){
        var dic = '/dictionary/xml/autolink/word/';
        asin = document.URL.replace(/http\:\/\/(.*)\/dictionary\/word\//,'');
        asin = asin.replace(/.html$/,"");

    } else {
        var dic = '/dictionary/xml/autolink/article/';
    }

    j.ajax({
        url: dic + asin + '.xml',
        type: 'GET',
        dataType: 'xml',
        timeout: 1000,
        async: false,
        cache: false,
        error: function(){
            //alert('Error loading XML document');
            var ul = document.getElementById('keywordList');
            if(ul != null ){
                var keyword_str = '<ul class="list"><li>登録キーワードはありません</li></ul>';
                ul.innerHTML = ul.innerHTML + keyword_str;
            };
        },
        success: function(xml){
            // do something with xml

            var type = '';
            var contents = new Array();
            type = j(xml).find("type").text();

            // 記事もしくは辞書及び記事だった場合動的・静的の制御

            // 記事で動的だった場合
            if(type == 'dynamic'){
                j(xml).find("html_id").each(function(){
                    var lists = new Array();
                    var line_name = j(this).text();
                    contents[line_name] = document.getElementById(line_name);

                    var word_list = this.parentNode.getElementsByTagName("word");
                    var id_list = this.parentNode.getElementsByTagName("id");

                    for(var ce=0; ce<word_list.length; ce++){
                        lists[ce] = new Array();

                        lists[ce]['url'] = '/dictionary/word/' + id_list[ce].firstChild.nodeValue + '.html';

                        var word_tmp = word_list[ce].firstChild.nodeValue;
                        lists[ce]['word'] = word_tmp;
                    }

                    // 置換するため、HTMLの一部と単語、URLのリストを渡す
                    result = Hilite.hiliteHTML( contents[line_name].innerHTML, lists);

                    // 結果をHTMLに埋め込む
                    contents[line_name].innerHTML = result;
                });




            // 記事で静的だった場合
            } else if( type == 'static' ){
                var url = document.URL;
                if( !url.match(/.*index\.html$/)){
                    url = url + 'index.html';
                }
                j(xml).find("html_id").each(function(){

                    // 今見ているURLと同じファイル名の下にある単語を見つける
                    file_name = j(this).text();

                    re = new RegExp(file_name);
                    if( url.match(re) ){

                        var lists = new Array();

                        var word_list = this.parentNode.getElementsByTagName("word");
                        var id_list = this.parentNode.getElementsByTagName("id");

                        for(var ce=0; ce<word_list.length; ce++){

                            lists[ce] = new Array();
                            lists[ce]['url'] = '/dictionary/word/' + id_list[ce].firstChild.nodeValue + '.html';

                            var word_tmp = word_list[ce].firstChild.nodeValue;
                            lists[ce]['word'] = word_tmp;
                            
                        }

                        // div タグをすべて取得
                        var ss1 = document.getElementsByTagName("div");
                        var ss2 = new Array();
                        var html = new Array();

                        // class="dword" の部分のみを取得
                        for (var i = 0; i < ss1.length; i++) {
                            var s = ss1[i];

                            var html_src = "";
                            if ( s.className.match(/dword/) || s.id.match(/infoUnit|profUnit/) ){

                                // 置換するため、HTMLの一部と単語、URLのリストを渡す
                                var result = Hilite.hiliteHTML( ss1[i].innerHTML, lists);

                                // 結果をHTMLに埋め込む
                                ss1[i].innerHTML = result;

                            };
                        };

                    };

                });


            // 辞書へのリンクだった場合(dictionary)
            } else {

                var url = document.URL;
                var ca = 0;
                var lists = new Array; 
                var dic_num = '';
                var dic_word = '';

                var word_list = xml.getElementsByTagName("word");
                var id_list = xml.getElementsByTagName("id");

                for(var ce=0; ce<word_list.length; ce++){

                    lists[ce] = new Array();
                    lists[ce]['url'] = '/dictionary/word/' + id_list[ce].firstChild.nodeValue + '.html';

                    var word_tmp = word_list[ce].firstChild.nodeValue;
                    lists[ce]['word'] = word_tmp;

                };

                var dicBody_src = document.getElementById('dicBody');

                var result = Hilite.hiliteHTML( dicBody_src.innerHTML, lists);
                dicBody_src.innerHTML = result;
            };


            var keyword_lists = new Array;
            var keyword_str = '';

            var word_list = xml.getElementsByTagName("word");
            var id_list = xml.getElementsByTagName("id");

            for( var ca=0; ca<word_list.length; ca++ ){
                keyword_lists[ca] = new Array();

                var word = word_list[ca].firstChild.nodeValue;
                var word_tmp = word;

                word_tmp = word_tmp.replace(/\r\n/g,'');
                word_tmp = word_tmp.replace(/\n/g,'');
                word_tmp = word_tmp.replace(/\t/g,'');
                word_tmp = word_tmp.replace(/\\/g,'\\\\');
                word_tmp = word_tmp.replace(/\(/g,'\\(');
                word_tmp = word_tmp.replace(/\)/g,'\\)');
                word_tmp = word_tmp.replace(/\?/g,'\\?');
                word_tmp = word_tmp.replace(/\$/g,'\\$');
                word_tmp = word_tmp.replace(/\^/g,'\\^');
                word_tmp = word_tmp.replace(/\./g,'\\.');
                word_tmp = word_tmp.replace(/\*/g,'\\*');
                word_tmp = word_tmp.replace(/\+/g,'\\+');
                word_tmp = word_tmp.replace(/\[/g,'\\[');
                word_tmp = word_tmp.replace(/\]/g,'\\]');
                word_tmp = word_tmp.replace(/\{/g,'\\{');
                word_tmp = word_tmp.replace(/\}/g,'\\}');
                word_tmp = word_tmp.replace(/\|/g,'\\|');

                keyword_lists[ca]['url'] = '/dictionary/word/' + id_list[ca].firstChild.nodeValue + '.html';

                var full_url = '<a href="' + keyword_lists[ca]['url'] + '">' + word_tmp + '</a>';

                re = new RegExp(full_url);
                if( !keyword_str.match(re) ){
                    keyword_str = keyword_str + '<li><a href="' + keyword_lists[ca]['url'] + '">' + word + '</a>';
                };
            };

            keyword_str = '<ul class="list">' + keyword_str + '</ul>';

            var ul = document.getElementById('keywordList');
            if(ul != null ){
                ul.innerHTML = ul.innerHTML + keyword_str;
            };

        // END success 
        }
    });

};

/**
 * Highlight a HTML string with a list of keywords.
 */
Hilite.hiliteHTML = function(html, query) {
    var re = new Array();
    for (var i = 0; i < query.length; i ++) {

        var word_tmp = query[i]['word'];
        word_tmp = word_tmp.replace(/\r\n/g,'');
        word_tmp = word_tmp.replace(/\n/g,'');
        word_tmp = word_tmp.replace(/\t/g,'');
        word_tmp = word_tmp.replace(/\\/g,'\\\\');
        word_tmp = word_tmp.replace(/\(/g,'\\(');
        word_tmp = word_tmp.replace(/\)/g,'\\)');
        word_tmp = word_tmp.replace(/\?/g,'\\?');
        word_tmp = word_tmp.replace(/\$/g,'\\$');
        word_tmp = word_tmp.replace(/\^/g,'\\^');
        word_tmp = word_tmp.replace(/\./g,'\\.');
        word_tmp = word_tmp.replace(/\*/g,'\\*');
        word_tmp = word_tmp.replace(/\+/g,'\\+');
        word_tmp = word_tmp.replace(/\[/g,'\\[');
        word_tmp = word_tmp.replace(/\]/g,'\\]');
        word_tmp = word_tmp.replace(/\{/g,'\\{');
        word_tmp = word_tmp.replace(/\}/g,'\\}');
        word_tmp = word_tmp.replace(/\|/g,'\\|');
        query[i]['decode_word'] = word_tmp;

        if (Hilite.exact)
            re.push('\\b'+query[i]['decode_word']+'\\b');
        else
            re.push(query[i]['decode_word']);
        }

        re = new RegExp('('+re.join("|")+')', "g");

        var subs;
        var stylemapper = {};
        for (var i = 0; i < query.length; i ++)
            stylemapper[query[i]['word']] = query[i]['url'];
        subs = function(match) {
            return '<A HREF="'+stylemapper[match]+'" class="dtword">'+match+
                '</A>';
    }

    html = html.replace(/&lt;/g, '<');
    html = html.replace(/&gt;/g, '>');
    html = html.replace(/&amp;/g, '&');
    html = html.replace(/&quot;/g, '"');
    html = html.replace(/&#039;/g, "'");
    var match = html.match(/(<a\s.*?>(.|\n)*?<\/a>)|(<[^<>\n]+>)|(&nbsp;)+/ig);

    var start = 0;
    var end = 0;
    var part = null;
    var result = '';
    var a_flag = 0;
    var a_match = "";

    if( match ){
        for(i = 0; i < match.length; i++){
            end = html.indexOf(match[i], start);
            part = html.substring(start, end);
            if( start != end && a_flag == 0 ) part = part.replace(re, subs);
            start = end + match[i].length
            part  = part + match[i];
            result += part;
        }
    }

    end = html.length;
    if( start != end ){
        part = html.substring(start, end);
        part = part.replace(re, subs);
        result += part;
    }

    return result;

};

/**
 * Highlight a DOM element with a list of keywords.
 */
Hilite.hiliteElement = function(elm, query) {
    if (!query)
	return;

    var oldhtml = elm.innerHTML;
    var newhtml = Hilite.hiliteHTML(oldhtml, query);

    if (oldhtml != newhtml)
        elm.innerHTML = newhtml;
};

/**
 * Highlight a HTML document using keywords extracted from document.referrer.
 * This is the main function to be called to perform search engine highlight
 * on a document.
 *
 * Currently it would check for DOM element 'content', element 'container' and
 * then document.body in that order, so it only highlights appropriate section
 * on WordPress and Movable Type pages.
 */
Hilite.hilite = function() {
    // If 'debug_referrer' then we will use that as our referrer string
    // instead.
    var q = Hilite.debug_referrer ? Hilite.debug_referrer : document.referrer;
    var e = null;
    q = Hilite.decodeReferrer(q);
    if (q && ((e = document.getElementById('dicBody')) ||
              (e = document.getElementById('box00')) ||
              (e = document.getElementById('content')) ||
              (e = document.getElementById('container')) ||
              (e = document.body)))
    {
	Hilite.hiliteElement(e, q);
    }
};

// Trigger the highlight using the onload handler.
if (Hilite.onload) {
  if (window.onload) {
        Hilite._old_onload = window.onload;
        window.onload = function(ev) {
            Hilite._old_onload(ev);
            Hilite.hilite();
        };
    } else {
        window.onload = Hilite.hilite;
    }
}


