$(function() {

var el, res, sel, val,
    options = {
        asHtmlID: 'autosuggest',
        selectedItemProp: "name",
        searchObjProps: "name"
    },
    data = [
        {value: "21", name: "Mick Jagger"},
        {value: "43", name: "Johnny Storm"},
        {value: "46", name: "Richard Hatch"},
        {value: "54", name: "Kelly Slater"},
        {value: "55", name: "Rudy Hamilton"},
        {value: "79", name: "Michael Jordan"},
        {value: "76", name: "姚明"}
    ],
    keyCode = {
        DEL:    8,
        TAB:    9,
        ENTER:  13,
        ESC:    27,
        UP:     38,
        DOWN:   40,
        J:      74,
        COMMA:  188
    };

function create(d, opts) {
    data = d || data;
    options = opts || options;

    return $('<input type="text" name="autosuggest" value=""></input>')
        .appendTo("#container").autoSuggest(data, options);
}

function selections() {
    return $("#as-selections-autosuggest li.as-selection-item");
}

function results() {
    return $("#as-results-autosuggest li.as-result-item");
}

function value() {
    return $("#as-values-autosuggest");
}

function remove() {
    $("#as-results-autosuggest, #as-selections-autosuggest").remove();
}

function debug() {
    window.console && console.debug.apply(console, arguments);
}

module("AutoSuggest TestCases");

test("Type J and select \"Michael Jordan\"", function() {
    el = create();
    // Type "J"
    // NOTE: Keydown event does not actually change the value of input,
    // You have to do this manually, and trigger the event later.
    el.focus();
    el.val("J");
    el.simulate("keydown", {"keyCode": keyCode.J});

    // Wait for building results
    stop();
    setTimeout(function() {
        // Here goes three suggestions
        res = results();
        equals(res.length, 3, "Should suggest three names");
        equals($(res[0]).text(), "Mick Jagger", "Should be Mick Jagger");
        equals($(res[1]).text(), "Johnny Storm", "Should be Johnny Storm");
        equals($(res[2]).text(), "Michael Jordan", "Should be Michael Jordan");

        // Select Michael Jordan
        $(res[2]).simulate("click");
        sel = selections();
        equals(sel.length, 1, "Should have one name");
        equals($(sel[0]).text(), "×Michael Jordan", "Should be Michael Jordan");
        equals($(sel[0]).attr('data-value'), "79", "Should set data-value on selection");
        equals(value().val(), ",79,", "Should be 79");

        start();
        remove();
    }, 500);
});

test("Type \"Yao Ming\" and select it by COMMA", function() {
    el = create();
    // Type "Yap Ming" and ","
    el.focus();
    el.val("Yao Ming");
    el.simulate("keydown", {"keyCode": keyCode.COMMA});

    sel = selections();
    equals(sel.length, 1, "Should have one name");
    equals($(sel[0]).text(), "×Yao Ming", "Should be Yao Ming");
    equals(value().val(), ",Yao Ming,", "Should be Yao Ming");
    remove();
});

test("Type \"Yao Ming\" and select it by TAB", function() {
    el = create();
    // Type "Yap Ming" and "\t"
    el.focus();
    el.val("Yao Ming");
    el.simulate("keydown", {"keyCode": keyCode.TAB});

    sel = selections();
    equals(sel.length, 1, "Should have one name");
    equals($(sel[0]).text(), "×Yao Ming", "Should be Yao Ming");
    equals(value().val(), ",Yao Ming,", "Should be Yao Ming");
    remove();
});

test("Press enter to select suggestion", function() {
    el = create();

    el.focus();
    el.val("J");
    el.simulate("keydown", {"keyCode": keyCode.J});

    stop();
    setTimeout(function() {
        res = results();

        // Mouse over the suggestion
        $(res[1]).simulate("mouseover");
        ok($(res[1]).hasClass("active"), "Should be highlighted");

        // Press enter key to select it
        el.simulate("keydown", {"keyCode": keyCode.ENTER});

        sel = selections();
        equals(sel.length, 1, "Should have one name");
        equals($(sel[0]).text(), "×Johnny Storm", "Should be Johnny Storm");
        equals(value().val(), ",43,", "Should be 43");

        start();
        remove();
    }, 500);
});

test("Press arrow keys to move the selection up and down", function() {
    el = create();

    el.focus();
    el.val("J");
    el.simulate("keydown", {"keyCode": keyCode.J});

    stop();
    setTimeout(function() {
        res = results();

        // Move down to first suggest result
        el.simulate("keydown", {"keyCode": keyCode.DOWN});
        ok($(res[0]).hasClass('active'), "Should be highlighted");

        // Move down to last suggest result
        el.simulate("keydown", {"keyCode": keyCode.DOWN});
        el.simulate("keydown", {"keyCode": keyCode.DOWN});
        ok($(res[2]).hasClass("active"), "Should be highlighted");

        // None of results should be highlighted
        el.simulate("keydown", {"keyCode": keyCode.DOWN});
        $.each(res, function() {
            ok(!$(this).hasClass("active"), "Should not be highlighted");
        });

        // Move back to first suggest result
        el.simulate("keydown", {"keyCode": keyCode.DOWN});
        ok($(res[0]).hasClass('active'), "Should be highlighted");

        // Now we move up...
        el.simulate("keydown", {"keyCode": keyCode.UP});
        $.each(res, function() {
            ok(!$(this).hasClass("active"), "Should not be highlighted");
        });

        // Move back to last suggest result
        el.simulate("keydown", {"keyCode": keyCode.UP});
        ok($(res[2]).hasClass("active"), "Should be highlighted");

        start();
        remove();
    }, 500);
});

test("Click close button to remove a name", function() {
    el = create();

    el.focus();
    el.val("Yao Ming");
    el.simulate("keydown", {"keyCode": keyCode.TAB});

    sel = selections();
    equals(sel.length, 1, "Should have one name");

    // Click the close button
    $(sel[0]).find("a.as-close").simulate("click");

    sel = selections();
    equals(sel.length, 0, "Should have no name left");
    equals(value().val(), ",", "Should have no name left");
    remove();
});

test("Press delete key twice to remove a name", function() {
    el = create();

    el.focus();
    el.val("Yao Ming");
    el.simulate("keydown", {"keyCode": keyCode.COMMA});

    sel = selections();
    equals(sel.length, 1, "Should have one name");

    // First time press delete key
    el.simulate("keydown", {"keyCode": keyCode.DEL});

    sel = selections();
    ok($(sel[0]).hasClass("selected"), "Should be selected");

    // Second time press delete key
    el.simulate("keydown", {"keyCode": keyCode.DEL});

    sel = selections();
    equals(sel.length, 0, "Should have no name left");
    equals(value().val(), ",", "Should have no name left");
    remove();
});

test("Use function for data source", function() {
    var wasCalled = false;
    function get_data(query, next) {
        wasCalled = true;
        next([{value: '123', name: 'zzzfffgg'}], query);
    }

    el = $('<input type="text" name="autosuggest" value=""></input>')
        .appendTo("#container").autoSuggest(get_data, options);

    el.focus();
    el.val("Y")
    el.simulate("keydown", {"keyCode": keyCode.Y});
    stop();
    setTimeout(function() {
      equals(wasCalled, true, "Was the callback called?");
      start();
      remove();
    }, 500);
});

test("Add and remove from code", function() {
    var callbacks;
    var opts = $.extend({}, options, {
        start: function(_callbacks) {
            callbacks = _callbacks;
        }
    });
    el = create('', opts);

    callbacks.add(data[0]);
    equals(selections().length, 1, "Should select using a callback.");

    callbacks.remove(data[1].value);
    equals(selections().length, 1, "Should not remove anything when unselected value is removed.");

    callbacks.remove(data[0].value);
    equals(selections().length, 0, "Should remove using a callback.");
});

test("Add extraParams with function (instead of ONLY a string)", function() {


    $('#container').append('<input type="checkbox" id="test-as-location" value="1" checked="checked" />');

    var opts = $.extend({}, options, {
        extraParams: function()
        {
            var checked = $('#test-as-location').is(':checked') ? 1 : 0;
            return '&specific_location=' + checked;
        }
    });

    var old_getJSON = $.getJSON;

    $.getJSON = function(url){
        equals(url, "data.html?q=J&specific_location=1");
        return old_getJSON.apply(this, arguments);
    }

    stop();

    $(document).bind('ajaxStop.extraParams', function(){
        start();
        // Restore it for later tests.
        $.getJSON = old_getJSON
        // Cleanup
        remove();
        $('#test-as-location').remove();
        $(document).unbind('ajaxStop.extraParams');
    });

    el = create('data.html', opts);

    el.focus();
    el.val("J");
    el.simulate("keydown", {"keyCode": keyCode.J});





});

});
;