
var Search = function(el_input, el_results, inactive_text)
{
    this.el_input = el_input;
    this.el_results = el_results;
    this.el_hits = $();
    this.inactive_text = inactive_text;

    this.autocompleteTime = 150;
    this.queryLoading = false;

    this.keyboardNav = false;
    this.selection = false;

    this.bindEvents();
    this.setInactive();
}
Search.prototype.bindEvents = function(query)
{
    var self = this;
    
    // 'autocomplete' behaviour
    var timer;
    $(this.el_input).keypress(function(e)
    {
        if (self.keyboardNav)
        {
            if (e.keyCode == 40) // down
                return self.selectNext();
            if (e.keyCode == 38) // up
                return self.selectPrev();
            if (e.keyCode == 13) // enter
                return self.visitCurrent();
            if (e.keyCode == 27) // escape
                return self.clear();
        }
        clearTimeout(timer);
        timer = setTimeout(function()
        {
            var query = $(self.el_input).val();
            self.query(query);
        }, self.autocompleteTime);
    });

    // focus and blur
    $(this.el_input).focus(function()
    {
        self.setActive();
    }).blur(function()
    {
        if ($(this).val() != '')
            return;
        self.setInactive();
    });

    $(this.el_input).parent().find('.go').click(function()
    {
        self.openSearchPage();
    });

    this.el_close = $(this.el_input).parent().find('.close').click(function()
    {
        self.clear();
    });
};
Search.prototype.openSearchPage = function()
{
    if ($(this.el_input).is('.inactive'))
        return;
    var query = $(this.el_input).val();
    var base = RegExp("http://[^/]+/").exec(window.location);
    window.location = base + 'search?q=' + query;
};
Search.prototype.clear = function()
{
    var self = this;
    setTimeout(function()
    {
        self.setInactive();
        self.showResults('');
        $(self.el_input).blur();
    });
};
Search.prototype.setActive = function()
{
    var $el = $(this.el_input);
    $el.removeClass('inactive');
    if ($el.val() == this.inactive_text)
        $el.val('');
};
Search.prototype.setInactive = function()
{
    $(this.el_input).addClass('inactive').val(this.inactive_text);
};
Search.prototype.query = function(query)
{
    var self = this;

    if (!query)
        return self.showResults('');

    if (query == this.queryLoading)
        return;

    this.queryLoading = query;
    var spinner = $(this.el_input).parent().find('.spinner').show();

    $.ajax({
        url: '/search',
        method: 'GET',
        data: { a: 1, q: query },
        dataType: 'html',
        success: function(html)
        {
            if (self.queryLoading != query)
                return;
            self.queryLoading = false;
            spinner.hide();
            self.showResults(html);
        }
    });
};
Search.prototype.showResults = function(html)
{
    var self = this;

    var r = $(this.el_results).html(html);
    r[html?'show':'hide']();
    this.el_close[html?'show':'hide']();

    this.el_hits = $('.hit', this.el_results);
    // enable keyboard navigation of there's a result
    this.keyboardNav = !!this.el_hits.length;
    this.selection = false;
    this.updateSelection();

    // bind mouseover result events
    var i = 0;
    this.el_hits.each(function()
    {
        var n = i;
        $(this).bind('mouseover', function()
        {
            self.selection = n;
            self.updateSelection();
        })
        i++;
    });
};
Search.prototype.updateSelection = function()
{
    this.el_hits.removeClass('highlight');
    if (this.selection !== false)
        this.el_hits.eq(this.selection).addClass('highlight');
};
Search.prototype.selectNext = function()
{
    if (this.selection === false)
        this.selection = 0;
    else
        this.selection+= 1;
    if (this.selection >= this.el_hits.length)
        this.selection = false;
    this.updateSelection();
};
Search.prototype.selectPrev = function()
{
    if (this.selection === false)
        this.selection = this.el_hits.length - 1;
    else
        this.selection+= -1;
    if (this.selection < 0)
        this.selection = false;
    this.updateSelection();
};
Search.prototype.visitCurrent = function()
{
    if (this.selection === false)
        return this.openSearchPage();
    var href = this.el_hits.eq(this.selection).attr('href');
    window.location = href;
};

