﻿jQuery.fn.watermark = function(defaultValue, options) {

    var input = this;
    var opts = jQuery.extend({ currentValue: input.val() }, jQuery.fn.watermark.defaults, options);

    function applyWatermark() {
        input.addClass(opts.defaultClass);
        input.val(defaultValue);
    }

    input.bind("blur", function() {
        if (input.val() == "") applyWatermark();
    });

    input.bind("focus", function() {
        if (input.hasClass(opts.defaultClass)) {
            input.val("");
            input.removeClass(opts.defaultClass);
        } else {
            input.select();
        }
    });

    if (opts.currentValue == "") applyWatermark();
}

jQuery.fn.watermark.defaults = {
    defaultClass: 'defaulted'
};

function clearSlidingTimeout(state) {
    clearInterval(state.__slidingTimeout);
}

function slidingTimeout(state, code, delay) {
    clearSlidingTimeout(state);
    state.__slidingTimeout = setTimeout(code, delay);
}

var QueryStatusType = {
    Querying: 0,
    Empty: 1,
    Success: 2,
    Failed: 3
}

function configureSearch(currentSearchText, defaultSearchText, suggestionsService) {

    $("#q").watermark(defaultSearchText, { currentValue: currentSearchText });

    /* TEMP */
    var queryingHtml    = "<span class=\"highlight\">Searching for matches</span>";
    var queryErrorHtml  = "<span class=\"highlight\">An unexpected error occurred when querying the server, no results could be determined. Please try again later.</span>";
    var queryEmptyHtml  = "<span class=\"highlight\">No results found</span>";
    
    var cq;
    var cqdex = 0;

    var searchField = $("#q")
        .attr('autocomplete', 'off');

    var visualField = searchField.parent();

    var fadeBackEl = document.createElement('div');

    $("#searchPanel").after(fadeBackEl);    
    
    var fadeBack = $(fadeBackEl)
        .attr('id', 'searchFadeCover')
        .css('opacity', 0)
        .hide();
    
    var searchPanelEl = document.createElement('div');

    visualField.after(searchPanelEl);
    
    var searchPanel = $(searchPanelEl)
        .addClass('inlineSearchPanel')
        .hide();

    var searchForm = $("#searchForm")
        .submit(function() {
            return false;
        })
        .css({ 
            position: 'relative',
            zIndex: 999
        });

    var magnifyButtonEl = document.createElement('div');
    var magnifyButton = $(magnifyButtonEl)
        .addClass('magnifyIcon');
    
    var clearButtonEl = document.createElement('div');
    var clearButton = $(clearButtonEl)
        .addClass('clearIcon')
        .click(function() {
            searchField.val('').focus();
        });

    $("#searchButton")
        .before(magnifyButton)
        .before(clearButton)
        .remove();

    /* --- */
    
    var showResetButton = function() {
        magnifyButton.hide();
        clearButton.show();
    }

    var hideResetButton = function() {
        magnifyButton.show();
        clearButton.hide();
    }

    var showPanel = function() {
        fadeBack.show().stop().animate({ opacity: .23 }, { duration: 200 });
        visualField.css("border", "solid 1px #fff");
        searchPanel.show();
    }

    var hidePanel = function() {
        fadeBack.stop().animate({ opacity: 0 }, { duration: 200, complete: function() { fadeBack.hide(); } });
        visualField.css("border", "solid 1px #ccc");
        searchPanel.hide();
    }

    /* --- */

    var generateResultsHtml = function(q, data) {

        var escaped = escape(q);

        var sb = "<div class=\"sectionBar\">" +
                     "<span class=\"highlight\">Top 20 results</span>" +
                     " &nbsp;|&nbsp; " +
                     "<a href=\"/search?q=" + escaped + "\">All results</a>" +
                     "</div>" +
                     "<div class=\"group-listings\">";

        var count = data.length;

        for (var i = 0; i < count; i++) {
            var group = data[i];

            var itemsCount = group.Items.length;

            if (itemsCount > 0) {
                sb += "<div class=\"" + group.CssName + "\">" +
                          "<h1>" + group.Name + "</h1>" +
                          "<ul>";

                for (var j = 0; j < itemsCount; j++) {
                    var part = group.Items[j];
                    sb += "<li><a href=\"" + part.DetailsUrl + "?q=" + escaped + "\">" + part.Title + "</a></li>";
                }

                sb += "</ul></div>";
            }
        }

        sb += "</div>";

        return sb;

    }

    var onQueryUpdate = function(status, q, data) {
        if (status == QueryStatusType.Querying) {
            searchPanel.html(queryingHtml);
        } else if (status == QueryStatusType.Empty) {
            searchPanel.html(queryEmptyHtml);
        } else if (status == QueryStatusType.Success) {
            searchPanel.html(generateResultsHtml(q, data));
        } else if (status == QueryStatusType.Failed) {
            searchPanel.html(queryErrorHtml);
        }
    }

    var isEmptyData = function(data) {

        if (!data) return true;

        var count = data.length;

        if (count == 0) return true;

        for (var i = 0; i < count; i++) {
            var group = data[i];
            var itemsCount = group.Items.length;
            if (itemsCount > 0) return false;
        }

        return true;
    }

    function runServiceQuery(q) {

        var params = {
            url: suggestionsService,
            processData: true,
            data: { q: q, dt: new Date().getTime() },
            dataType: "json",
            qdex: ++cqdex,
            success: function(data) {
                if (params.qdex == cqdex) {
                    if (isEmptyData(data)) {
                        onQueryUpdate(QueryStatusType.Empty, q);
                    } else {
                        onQueryUpdate(QueryStatusType.Success, q, data);
                    }
                }
            },
            error: function() {
                if (params.qdex == cqdex) {
                    onQueryUpdate(QueryStatusType.Failed, q);
                }
            }
        };

        $.ajax(params);
    }

    function runQuery(q, noDelay) {

        if ((q.length == 0) || (q == cq)) return;

        cq = q;
        
        onQueryUpdate(QueryStatusType.Querying);

        if (noDelay) {
            runServiceQuery(q);
        } else {
            slidingTimeout(searchField, function() {
                runServiceQuery(q);
            }, 400);
        }
    }

    var parseRawQuery = function(q) {
        return q.replace(/^\s+|\s+$/g, '');
    }

    var getQuery = function() {
        return parseRawQuery(searchField.val());
    }

    var updatePanelVisibility = function() {
        var q = getQuery();
        if (q.length > 0) {
            showPanel();
            showResetButton();
        } else {
            hidePanel();
            hideResetButton();
        }
    }

    searchField
        .bind('focus', updatePanelVisibility)
        .bind('keyup', function() {
            runQuery(getQuery());
            updatePanelVisibility();
        });

    fadeBack.bind('click', hidePanel);

    if (currentSearchText.length == 0) {
        hideResetButton();
    } else {
        runQuery(getQuery(), true);
        showResetButton();
    }

    /* --- */

    $(document).ready(function() {

        $("a[href^='/search/tag/']").click(function() {
            var url = $(this).attr("href");
            var dex = url.lastIndexOf("/");
            var tag = url.substring(dex + 1);

            if (tag.indexOf('%20') > -1)
                tag = '"' + tag + '"';

            var qry = "Tags: " + unescape(tag);

            runQuery(parseRawQuery(qry), true);
            searchField.focus().val(qry).focus();

            return false;
        });

    });
    
    return;
}