/*
 * Wrapper function to abstract the jQuery UI Autocompleter widget
 *
 * This originally started as its own widget to extend jQuery UI but turned into
 * this function call instead since it's rather specific to the dispatch loop in
 * /index.php for the Crossroads custom CMS stuff.
 *
 * !! Requires jQuery & jQuery UI to already be loaded !!
 * Tested with jQuery 1.6.1 & jQuery UI 1.8.13, FYI
 *
 * Author: Mike Firesheets
 * Date: 5-17-2011
 */

/*
 * Include this script on the page and then call makeAutocompleter() to turn
 * whatever input control into autocomplete-aware. Optionally pass in an object
 * of options you want to override the defaults.
 *
 * input
 *      id attribute of the input control user will type into. Can optionally
 *          include the "#" in front to be a jQuery selector, or be the jQuery
 *          object itself.
 *      default: "#ac_input"
 * inputResult
 *      name of field in search results JSON object to populate the input control
 *      default: "name"
 * update
 *      id attribute of the input control to be updated when user selects result.
 *          Generally this is a hidden input & will store a person id or account num.
 *          Can optionally include the "#" in front to be a jQuery selector, or
 *          be the jQuery object itself.
 *      default: "#ac_result"
 * updateResult
 *      name of the field in search results JSON object to populate the input control
 *      default: "id"
 * indicator
 *      id attribute of the element to be updated to indicate that the autocompleter
 *          is properly selected or not. Can optionally include te "#" in front
 *          to be a jQuery selector, or be the jQuery object itself.
 *      default: undefined
 * valid
 *      HTML string to replace indicator.innerHTML when a valid search result has
 *          been chosen.
 *      default: '<img src="/img/icn/blue-check.gif" name="Name is valid" title="Name is valid">',
 * invalid
 *      HTML string to replace indicator.innerHTML when no result has been chosen
 *          or an invalid choice has been made.
 *      default: '<img src="/img/icn/blue-bang.gif" name="Name is not valid" title="Name is not valid">',
 * urldata
 *      object of query parameters specifying the server-side URL to call for
 *          search results. This is passed unaltered as the 2nd argument to
 *          jQuery.getJSON()
 *      default: {
 *              action: "viewpage",
 *              ssl: true,
 *              skipheader: true,
 *              filepath: "site/jpersonLookup.php"
 *        }
 * fields
 *      array of objects detailing how to display each item of search results.
 *      Consists of two basic parts, the name of result data coming from the JSON
 *          object and the label to prepend to that value for display. Both can
 *          optionally have CSS classes applied to them.
 *          See htdocs/css/jqueryui.autocompleter.css for the available classes.
 *      default: [
 *              { label: "", data: "name", lclass: "ac_none", dclass: "ac_title" },
 *              { label: "Email:", data: "email", lclass: "ac_label", dclass: "ac_field" },
 *              { label: "Login:", data: "username", lclass: "ac_label", dclass: "ac_field" },
 *              { label: "Address:", data: "address1", lclass: "ac_label", dclass: "ac_field" },
 *              { label: "Address:", data: "address2", lclass: "ac_blank", dclass: "ac_field" },
 *              { label: "Address:", data: "addressCSZ", lclass: "ac_blank", dclass: "ac_field" },
 *              { label: "", data: "date", lclass: "ac_blank", dclass: "ac_smallfield" }
 *          ]
 *
 *          The default will spit out something like the following:
 *            JOHN DOE
 *              Email:   j.doe@example.com
 *              Login:   jdoe1980
 *              Address: 123 Main Street
 *                       Apt #27
 *                       Eerie, IN 12345
 *              member since May 2009
 * onSelect
 *      object with a function pointer to call when user selects a result. If
 *          override is true, the onSelect event for this plugin AND the default
 *          jQuery UI onSelect event WILL NOT GET CALLED
 *      default: {
 *            func: undefined,
 *            override: false
 *        }
 */
function makeAutocompleter(options) {
    if (!jQuery) throw new Error('Could not find jQuery loaded!');
    if (!jQuery.ui) throw new Error('Could not find jQuery UI loaded!');

(function($) {
    var lastXhr,
    cache = {},
    settings = {
        input: "#ac_input",
        inputResult: "name",
        update: "#ac_result",
        updateResult: "id",
        indicator: undefined,
        valid: '<img src="/img/icn/blue-check.gif" name="Name is valid" title="Name is valid">',
        invalid: '<img src="/img/icn/blue-bang.gif" name="Name is not valid" title="Name is not valid">',
        urldata: {
            action: "viewpage",
            ssl: true,
            skipheader: true,
            filepath: "site/jpersonLookup.php"
        },
        fields: [
            { label: "", data: "name", lclass: "ac_none", dclass: "ac_title" },
            { label: "Email:", data: "email", lclass: "ac_label", dclass: "ac_field" },
            { label: "Login:", data: "username", lclass: "ac_label", dclass: "ac_field" },
            { label: "Address:", data: "address1", lclass: "ac_label", dclass: "ac_field" },
            { label: "Address:", data: "address2", lclass: "ac_blank", dclass: "ac_field" },
            { label: "Address:", data: "addressCSZ", lclass: "ac_blank", dclass: "ac_field" },
            { label: "Phone:", data: "phone", lclass: "ac_label", dclass: "ac_field" },
            { label: "", data: "date", lclass: "ac_blank", dclass: "ac_smallfield" }
        ],
        onSelect: {
            func: undefined,
            override: false
        }
    };

    if (options) {
        $.extend(settings, options);
    }

    if (typeof settings.input == 'object') {
        settings.input = "#" + $(settings.input).attr('id');
    } else if (typeof settings.input == 'string' && settings.input[0] != "#") {
        settings.input = "#" + settings.input;
    }
    if (typeof settings.update == 'object') {
        settings.update = "#" + $(settings.update).attr('id');
    } else if (typeof settings.update == 'string' && settings.update[0] != "#") {
        settings.update = "#" + settings.update;
    }
    if (typeof settings.indicator == 'object') {
        settings.indicator = "#" + $(settings.indicator).attr('id');
    } else if (typeof settings.indicator == 'string' && settings.indicator[0] != "#") {
        settings.indicator = "#" + settings.indicator;
    }


    $(settings.input)
        .bind("change", function(e) {
            // Bug if text changes to be less than minLength
            if (this.value.length < 2) {
                $(settings.update).val('');
                settings.indicator && settings.indicator.length && $(settings.indicator).html(settings.invalid);
            }
        })
        .autocomplete({
            minLength: 2,
            source: function(request, response) {
                $(settings.update).val('');
                settings.indicator && settings.indicator.length && $(settings.indicator).html(settings.invalid);

                var term = request.term;
                if (term in cache) {
                    response(cache[term]);
                    return;
                }
                settings.urldata.name = request.term;
                lastXhr = $.getJSON(
                    '/index.php',
                    settings.urldata,
                    function(data, status, xhr) {
                        if (!data || data.length == 0) {
                            // No results
                            $(settings.input).removeClass('ac_loading');
                        }
                        cache[term] = data;
                        if (xhr === lastXhr) {
                            response(data);
                        }
                    }
                );
            },
            search : function(event, ui) {
                $(settings.input).addClass('ac_loading');
            },
            focus : function(event, ui) {
                $(settings.input).val(ui.item[settings.inputResult]);
                return false;
            },
            open : function(event, ui) {
                $(settings.input).removeClass('ac_loading');
            },
            select : function(event, ui) {
                if (settings.onSelect.func && settings.onSelect.override) {
                    return settings.onSelect.func(event, ui, this);
                }
                $(settings.input).val(ui.item[settings.inputResult]);
                $(settings.update).val(ui.item[settings.updateResult]);
                settings.indicator && settings.indicator.length && $(settings.indicator).html(settings.valid);
                if (settings.onSelect.func) {
                    return settings.onSelect.func(event, ui, this);
                }
                if(ui.item['url']){ // if url is set, go to it
                  window.location.href=ui.item['url'];
                }
                return false;
            }
        })
        .data('autocomplete')._renderItem = function(ul, result) {
            var a = $('<a/>').css({'border-bottom': '1px dotted lightgray', 'margin-bottom': '3px'});
            for (var i=0; i < settings.fields.length; i++) {
                var r = settings.fields[i];
                a.append(makeDataRow(r.label, result[r.data], r.lclass, r.dclass));
            }
            return $('<li></li>').data('item.autocomplete', result).append(a).appendTo(ul);
        };
})(jQuery)
}


function makeDataRow(label, data, lclass, dclass) {
    if (lclass == null || lclass.length == 0) {
        lclass = 'ac_label';
    }
    if (dclass == null || dclass.length == 0) {
        dclass = 'ac_field';
    }

    if (data != null && data.length) {
        var d = jQuery('<div/>');
        jQuery('<span/>').addClass(lclass).html(label).appendTo(d);
        jQuery('<span/>').addClass(dclass).html(data).appendTo(d);
        return d;
    }
    return null;
}

