// create new search
window.Search = {
    Init: function (htmlObject, excludeTextField)
    {
        this.HtmlObject = htmlObject;
        this.Prefix = '<span style="background-color:pink">';
        this.Postfix = '</span>';

        if (excludeTextField == null) excludeTextField = false;
        this.Show(excludeTextField);

        if (window.Filter != null && Filter.Active == true) {
            Filter.OnChange.Bind(this.FilterChange, this);
        }
    },
     
    Show: function (excludeTextField)
    {
        var html = "";

        // close search button
        html += '<div id="search_header" class="menu_header">';
        html += '<a id="search_close" onclick="ToggleSearch(); return false;" class="close_button"></a>';
        html += '</div>';


        // search index
        html += '<iframe id="searchIndex" src="' + window.RootUrl + 'searchIndex.htm" style="display: none;" onload="Search.LoadHaystack(this);"></iframe>';

        html += '<div id="search_input">';

        if (excludeTextField != true) {
            var text = GetParameter("search");
            if (text == null) text = "";

            html += '<div id="search_string">';
            html += '<input type="text" id="search_text" onkeypress="if (event.keyCode==13) Search.Search();" value="' + text + '"/>';
            html += '<input id="search_button" type="button" value="' + Translation.btn_search + '" onclick="Search.Search();"/>';
            html += '</div>';
        } else {
            var text = GetParameter("search");
            if (text == null) text = "";
            $("#search_text").val(text);
        }

        var wholeWord = GetParameter("wholeWord") === 'true';

        html += '<div id="search_wholeWord" class="search_option">';
        html += '<input id="search_wholeWord_checkbox" class="search_checkbox" type="checkbox" ' + (wholeWord? 'checked="checked"': '') +'/>';
        html += '<span id="search_wholeWord_caption" class="search_caption">' + Translation.lbl_wholeWord + '</span>';
        html += '</div>';


        var caseSensitive = GetParameter("caseSensitive") === 'true';

        html += '<div id="search_caseSensitive" class="search_option">';
        html += '<input id="search_caseSensitive_checkbox" class="search_checkbox" type="checkbox" ' + (caseSensitive? 'checked="checked"': '') +'/>';
        html += '<span id="search_caseSensitive_caption" class="search_caption">' + Translation.lbl_caseSensitive + '</span>';
        html += '</div>';

        html += '</div>';

        html += '<div id="search_results">' + Translation.msg_search_notFound + '</div>';
        html += '<div id="search_dms_results"></div>';

        this.HtmlObject.html(html);
    },

    FilterChange: function ()
    {
        // allow new search to occur with same parameters
        this.Params = null;

        // remove current results
        $("#search_results").html(Translation.msg_search_notFound);
    },

    LoadHaystack: function (haystackNode)
    {
        this.Haystack = $(haystackNode.contentWindow.document.body);
        if (GetParameter("search") != null){
            this.Search();
            if (this.HighlightNode != null) this.Highlight(this.HighlightNode);
        }
    },

    GetParams: function ()
    {
        return {
            Text: $("#search_text").val(),
            WholeWord: $("#search_wholeWord_checkbox").is(":checked"),
            CaseSensitive: $("#search_caseSensitive_checkbox").is(":checked")
        };
    },

    ParamsChanged: function ()
    {
        var params = this.GetParams();
        if (this.Params == null) return true;
        if (params.Text != this.Params.Text) return true;
        if (params.CaseSensitive != this.Params.CaseSensitive) return true;
        if (params.WholeWord != this.Params.WholeWord) return true;

        return false;
    },

    Search: function ()
    {
        // get parameters
        if (!this.ParamsChanged()) return;
        this.Params = this.GetParams();

        // Generate Regular Expression
        this.GenerateExpression();

        // notify that search is in progress
        var fResultContainer = $("#search_results");
        fResultContainer.html(Translation.msg_search_inProgress);

        //this.DmsSearch();

        // Excecute search
        window.setTimeout("Search.Finish();", 0);
    },

    Finish: function ()
    {
        // Execute search
        if (this.SearchExpression != null) {
            var result = this.SubSearch(this.Haystack);
            if (result != null) var results = result.SubResults;
            else var results = new Array();
        } else {
            var results = new Array();
        }

        // write results
        var fResultContainer = $("#search_results");

        // Create Results
        if (results.length == 0) {
            fResultContainer.html(Translation.msg_search_notFound);
        } else {
            fResultContainer.html(this.CreateResultTable(results));
        }
    },

    GenerateExpression: function ()
    {
        if (this.Params.Text == "") {
            this.SearchExpression = null;
            return;
        }

        var text = strip(this.Params.Text).replace(/([\\|^$()[\]{}.*+?])/g, '\\$1');

        // look for whole word
        if (this.Params.WholeWord == true) text = "\\b" + text + "\\b";

        // use casesensitive searching
        if (this.Params.CaseSensitive == true) this.SearchExpression = new RegExp(text, "g");
        else this.SearchExpression = new RegExp(text, "gi");
    },

    DmsSearch: function ()
    {
        var iframe = document.getElementById("dmsSearchResults");
        //iframe.src = "content/dmsSearchResults.htm";
    },

    LoadDmsResults: function (object)
    {
        var results = object.contentWindow.DmsSearchResults;

        if (results == null) return;

        var htmlObject = document.getElementById("search_dms_results");

        var html = '<table class="search_results_table" cellspacing="0">';
        html += this.CreateResultHeader();

        for (var i in results) {
            var result = results[i];
            html += this.CreateDmsResultRows(result.Id, result.SubResults, 0);
        }

        html += "</table>";

        htmlObject.innerHTML = html;

        return html;
    },

    CreateDmsResultRows: function (id, results, indent)
    {
        var html = '';

        // create result rows
        for (var i = 0; i < results.length; i++) {
            var result = results[i];

            html += this.CreateResultRow(id, result.Path, result.Count, false, indent);

            if (result.SubResults != null && result.SubResults.length > 0) {
                html += this.CreateDmsResultRows(id, result.SubResults, indent + 1);
            }
        }

        return html;
    },

    SubSearch: function (documentNode)
    {
        var fCount = 0;
        var fSubResults = new Array();

        var children = documentNode.children();

        for (var i = 0; i < children.length; i++) {
            var fCurrentNode = children.eq(i);

            if (fCurrentNode.attr('tagName') == "DIV") {
                // search childnodes
                var fResults = this.SubSearch(fCurrentNode);
                if (fResults != null) fSubResults.push(fResults);
            }
            else if (fCurrentNode.attr('tagName') == "P") {
                // find needles
                var fNodeText = fCurrentNode.text();
                var fMatch = this.SearchExpression.exec(fNodeText);

                while (fMatch != null) {
                    fCount++;
                    fMatch = this.SearchExpression.exec(fNodeText);
                }
            }
        }

        // add result if needles have been found
        if (fCount > 0 || fSubResults.length > 0) {
            return { Node: documentNode, Count: fCount, SubResults: fSubResults };
        } else {
            return null;
        }
    },

    Highlight: function (node)
    {
        this.GenerateExpression();
        var fResult = "";
        var fPost = "", fInput = node.html();
        var fMatch = this.SearchExpression.exec(fInput);
        var fIndex = 0, fLastIndex;

        while (fMatch != null) {
            // update regular expression info
            fLastIndex = fIndex;
            fIndex = this.SearchExpression.lastIndex;
            fPost = RegExp.rightContext;

            // make sure text is outside of html node
            var fHtmlMatch = fPost.match("<|>");
            if (fHtmlMatch == null || fHtmlMatch[0] != ">") // text is outside html
            {
                fResult += fInput.slice(fLastIndex, fIndex - fMatch[0].length);
                fResult += this.Prefix + fMatch[0] + this.Postfix;
            }
            else // text is inside a html node
            {
                fResult += fInput.slice(fLastIndex, fIndex);
            }

            // Find next
            fMatch = this.SearchExpression.exec(fInput);
        }

        // Add remaining text to the result
        fResult += fInput.slice(fIndex);

        // write result to document
        node.html(fResult);
    },

    CreateResultTable: function (results)
    {
        var html = '<table class="search_results_table" cellspacing="0">';
        html += this.CreateResultHeader();

        // create result rows
        for (var i = 0; i < results.length; i++) {
            var result = results[i];

            html += this.CreateResultRow(result.Node.attr('id'), result.Node.attr('title'), result.Node.attr('url'), result.Count, result.IsFiltered, 0);

            if (result.SubResults != null && result.SubResults.length > 0) {
                html += this.CreateNestedResultTable(result.SubResults, 1);
            }
        }

        html += "</table>";

        return html;
    },

    CreateNestedResultTable: function (results, nesting)
    {
        var html = '';

        // create result rows
        for (var i = 0; i < results.length; i++) {
            var result = results[i];
            html += this.CreateResultRow(result.Node.attr('id'), result.Node.attr('title'), result.Node.attr('url'), result.Count, result.IsFiltered, nesting);

            if (result.SubResults != null && result.SubResults.length > 0) {
                html += this.CreateNestedResultTable(result.SubResults, nesting + 1);
            }
        }

        return html;
    },

    CreateResultHeader: function ()
    {
        // create header
        html = '<tr id="search_results_header_row">';
        html += '<th align="left" id="search_results_header_title" class="search_results_header_cell search_results_title_column">' + Translation.lbl_searchResult_title + '</th>';
        html += '<th align="left" id="search_results_header_count" class="search_results_header_cell search_results_count_column">' + Translation.lbl_searchResult_count + '</th>';
        html += '</tr>';

        return html;
    },

    CreateResultRow: function (id, title, url, count, isFiltered, indent)
    {
        var result = "";
        var indentHtml = "";
        var outdentHtml = "";

        if (count == null) count = 0;
        if (isFiltered == null) isFiltered = false;
        if (indent == null) indent = 0;

        while (indent > 0) {
            indentHtml += '<div class="search_results_indent">';
            outdentHtml += '</div>';
            indent--;
        }

        var filterClass = "";
        if (isFiltered && Filter != null) {
            filterClass = "search_results_" + Filter.Type;
        }

        result += '<tr class="search_results_row ' + filterClass + '">';
        result += '<td class="search_results_title search_results_title_column">';
        result += indentHtml;


        if (url != null && url != "") {
            url = window.RootUrl + url + "?search=" + encodeURI(this.Params.Text) + "&caseSensitive=" + this.Params.CaseSensitive + "&wholeWord=" + this.Params.WholeWord;
            result += '<a class="search_results_node search_results_link" href="' + url + '">' + title + '</a>';
        }
        else {
            result += '<a class="search_results_node">' + title + '</a>';
        }

        result += outdentHtml;

        result += '</td>';
        result += '<td class="search_results_count search_results_count_column">' + count + '</td></tr>';

        return result;
    }
};


/**
Returns:
The text without whitespace at the start or the end.
*/
function strip(text)
{
    return text.match(/^\s*([\w\W]*?)\s*$/)[1];
}

// ============================================
// Url stuff
// ============================================
var _parameters = null;

function GetParameter(name)
{
    var parameters = GetParameters();
    return parameters[name];
}

function GetParameters()
{
    if (_parameters == null) {
        _parameters = {};
        var hash;
        var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
        for (var i = 0; i < hashes.length; i++) {
            hash = hashes[i].split('=');
            _parameters[hash[0]] = decodeURI(hash[1]);
        }
    }
    return _parameters;
}
