/**
 * coolMultiple jQuery plugin
 *
 * Transforms a select or a list of checkboxes into a nicer control.+
 * Tested with jQuery 1.3.2, 1.4.2
 * 
 * @todo auto-detect mode
 * @version 1.0
 * @author vlad fratila, vlad.fratila@gmail.com
 * 
 */

(function ($) {

    var methods = {
        'init': function (options) {
            var d = new Date();

            this.settings = {
                delText: 'delete',
                mode: 'select',
                _id: 'coolmulti_' + this.attr("id")
            };
            if (options) {
                this.settings = $.extend(this.settings, options);
            }

            var selectobj = this;
            selectobj.hide();


            selectobj.after('<div id="' + selectobj.settings._id + '" class="coolmulti clearfix"></div>');
            selectobj.wrapper = selectobj.parent().find("#" + selectobj.settings._id);
            selectobj.div = selectobj.wrapper.append('<div id="' + selectobj.settings._id + '_scrollbox" class="coolmulti-scrollbox"></div>').find('div#' + selectobj.settings._id + '_scrollbox');

            this.coolMultiple('init_select');


        },

        'init_select': function () {
            var selectobj = this;

            selectobj.find('option').each(function () {
                selectobj.div.append('<p id="' + selectobj.settings._id + '_o_' + $(this).val() + '">' + $(this).text() + '</p>');
                if ($(this).attr('selected')) {
                    selectobj.coolMultiple('select', $(this).val());
                }
            });

            selectobj.div.find('p').click(function () {
                var value = $(this).attr('id').replace(selectobj.settings._id + '_o_', '');
                if (!$(this).hasClass('coolmulti-selected')) {
                    selectobj.coolMultiple('select', value);
                }
                else {
                    selectobj.coolMultiple('deselect', value);
                }
            });
        },


        'select': function (o) {
            var selectobj = this;

            if (selectobj.settings.mode == 'select') {
                var tag = 'option';
            }


            var option = selectobj.find(tag + '[value="' + o + '"]');
            if (selectobj.settings.mode == 'select') {
                option.attr('selected', 'selected');
                var text = option.text();
            }


            $('p#' + selectobj.settings._id + '_o_' + o).addClass('coolmulti-selected');

        },

        'deselect': function (o) {
            var selectobj = this;

            if (selectobj.settings.mode == 'select') {
                var tag = 'option';
            }


            var option = selectobj.find(tag + '[value="' + o + '"]');

            if (selectobj.settings.mode == 'select') {
                option.attr('selected', '');
                var text = option.text();
            }


            $('p#' + selectobj.settings._id + '_o_' + o).removeClass('coolmulti-selected');

        }
    };

    $.fn.coolMultiple = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            if (console.log) console.log('Method ' + method + ' does not exist on jQuery.coolMultiple');
        }

        return this;

    };
})(jQuery);



jQuery.fn.extend({
    selectbox: function (options) {
        return this.each(function () {
            new jQuery.SelectBox(this, options);
        });
    }
});



jQuery.SelectBox = function (selectobj, options) {

    var opt = options || {};
    opt.inputClass = opt.inputClass || "selectbox";
    opt.containerClass = opt.containerClass || "selectbox-wrapper";
    opt.hoverClass = opt.hoverClass || "current";
    opt.currentClass = opt.selectedClass || "selected"
    opt.debug = opt.debug || false;
    opt.widthModifier = opt.widthModifier || 0;

    var elm_id = selectobj.id;
    var active = -1;
    var inFocus = false;
    var hasfocus = 0;

    var $outerContainer = setupOuterContainer();

    //jquery object for select element
    var $select = $(selectobj);
    // jquery container object
    var $container = setupContainer(opt);
    //jquery input object 
    var $input = setupInput(opt);

    var $selectButton = setupSelectButton();

    // hide select and append newly created elements
    $select.hide().before($outerContainer); //before($input).before($container);
    $outerContainer.append($input).append($selectButton).append($container);

    init();

    $selectButton
	.click(function () {
	    if (!inFocus) {
	        $container.toggle();
	    }
	})
	.focus(function () {
	    if ($container.not(':visible')) {
	        inFocus = true;
	        $container.show();

            // hack - hide buttons so they don't cut through select
	        if ($.browser.msie && parseInt($.browser.version.charAt(0)) <= 7) $("button").css("visibility", "hidden");

	    }
	});


    $(document).keydown(function (event) {
        if (hasfocus != 1) return;
        switch (event.keyCode) {
            case 38: // up
                event.preventDefault();
                moveSelect(-1);
                break;
            case 40: // down
                event.preventDefault();
                moveSelect(1);
                break;
            //case 9:  // tab                    
            case 13: // return
                event.preventDefault(); // seems not working in mac !
                $('li.' + opt.hoverClass).trigger('click');
                break;
            case 27: //escape
                hideMe();
                break;
        }
    });

    $(document).click(function (event) {
        if ($container.has(event.target).length == 0 && $container.is(':visible')) {
            //hideMe();
        } 
    });


    function hideMe() {
        hasfocus = 0;
        $container.hide();

        // hack - hide buttons so they don't cut through select
        if ($.browser.msie && parseInt($.browser.version.charAt(0)) <= 7) $("button").css("visibility","visible");
    }

    function init() {
        $container.append(getSelectOptions($input.attr('id'))).hide();
        var width = $select.width();
        $container.width(width + "px");
        $input.width(width + opt.widthModifier + "px");
        $outerContainer.width(width + "px");
        $selectButton.width(width + "px");
    }

    function setupContainer(options) {
        var container = document.createElement("div");
        $container = $(container);
        $container.attr('id', elm_id + '_container');
        $container.addClass(options.containerClass);
        return $container;
    }

    function setupOuterContainer() {
        $outerContainer = $("<div></div>");
        $outerContainer.addClass("selectBox");
        return $outerContainer;
    }

    function setupSelectButton() {
        $o = $("<div></div>");
        $o.addClass("selectButton");
        return $o;
    }


    function setupInput(options) {
        var input = document.createElement("input");
        var $input = $(input);
        $input.attr("id", elm_id + "_input");
        $input.attr("type", "text");
        $input.addClass(options.inputClass);
        $input.attr("autocomplete", "off");
        $input.attr("readonly", "readonly");
        $input.attr("tabIndex", $select.attr("tabindex")); // "I" capital is important for ie

        return $input;
    }

    function moveSelect(step) {
        var lis = $("li", $container);
        if (!lis) return;

        active += step;

        if (active < 0) {
            active = 0;
        } else if (active >= lis.size()) {
            active = lis.size() - 1;
        }

        lis.removeClass(opt.hoverClass);

        $(lis[active]).addClass(opt.hoverClass);
    }

    function setCurrent() {
        var li = $("li." + opt.currentClass, $container).get(0);
        var ar = ('' + li.id).split('_');
        var el = ar[ar.length - 1];
        $select.val(el);
        var $li = $(li);
        $input.val($li.html());
        //$opt = $select.find("option[value='" + $li.data("value") + "']");
        // $select.attr("selectedIndex", $select.find("option").index($opt));

        return true;
    }

    // select value
    function getCurrentSelected() {
        return $select.val();
    }

    // input value
    function getCurrentValue() {
        return $input.val();
    }

    function getSelectOptions(parentid) {
        var select_options = new Array();
        var ul = document.createElement('ul');
        $select.children('option').each(function () {
            if (opt.noBlanks && $(this).val() == "") return;
            var li = document.createElement('li');
            li.setAttribute('id', parentid + '_' + $(this).val());
            li.innerHTML = $(this).html();
            if ($(this).is(':selected')) {
                $input.val($(this).html());
                $(li).addClass(opt.currentClass);
            }
            ul.appendChild(li);
            $(li)
			.mouseover(function (event) {
			    hasfocus = 1;
			    jQuery(event.target, $container).addClass(opt.hoverClass);
			})
			.mouseout(function (event) {
			    hasfocus = -1;
			    jQuery(event.target, $container).removeClass(opt.hoverClass);
			})
			.click(function (event) {
			    var fl = $('li.' + opt.hoverClass, $container).get(0);
			    $('li.' + opt.currentClass).removeClass(opt.currentClass);
			    $(this).addClass(opt.currentClass);
			    setCurrent();
			    hideMe();
			})
            .data("value", $(this).val());
        });
        return ul;
    }

};

