$.fn.JellyfishCustomSelect = function () {
    // CustomSelect jQuery plug-in
    // based on Select Customizer by Dean Collins http://www.dblog.com.au
    // modified by Steven Anderson + Rich Reeves @ Jellyfish http://www.jellyfishcreative.co.uk
    return this.each(function () {
        var obj = $(this);
        var name = obj.attr('id');
        var id_slc_options = name + '_options';
        var id_icn_select = name + '_iconselect';
        var id_holder = name + '_holder';
        var custom_select = name + '_customselect';
        var listheight = 200;

        $.fn.addItems = function (data) {
            return this.each(function () {
                var list = this;

                $.each(data, function (index, itemData) {

                    var text = $(this).attr('Text');
                    var value = $(this).attr('Value');
                    var css = $(this).attr('Class');
                    var selected = $(this).attr('Selected');

                    if (text == undefined) text = itemData.text;
                    if (value == undefined) value = itemData.value;
                    if (css == undefined) css = $(this).attr('class');
                    if (selected == undefined) selected = $(this).attr('selected');

                    var $selectitem = $('<a></a>').addClass('option-item')
                        .attr('title', text)
                        .attr('rel', value)
                        .attr('href', '')
                        .html('<span>' + text + '</span>');

                    // Does the option have any classes?
                    $selectitem.addClass(css);
                    if (selected) $selectitem.addClass('selected');

                    // Is this the selected option?
                    //if ($(this).is(':selected')) $selectitem.addClass('selected');

                    // A custom option added by the user
                    if ($selectitem.hasClass('user')) {
                        var $removebtn = $('<a></a>').addClass('remove-btn')
                            .attr({ 'rel': itemData.value, 'title': 'Remove from quicklinks' })
                            .css({ 'position': 'absolute' })
                            .html('x');
                        $(list).append($removebtn);
                    }
                    $(list).append($selectitem);
                });

                $(list).find('.option-item').bind('click', bind_optionitem_click);
            });
        };

        var bind_optionitem_click = function (e) {
            e.preventDefault();
            update_select_value($(this));
            var customselect_container = $(this).closest('.custom-select-container').find('.selectbg');

            if ($(customselect_container).is('.autosubmit')) {
                $(this).closest('form').trigger('submit');
            }

            if ($(customselect_container).is('.cascading')) {
                process_cascading_changes($(customselect_container).attr('id'), $(this).attr("rel"));
            };

            hide_options_wrapper();
        };

        var update_select_value = function (e) {
            $(e).parent('.options-wrapper').find('.selected').removeClass("selected");
            $(e).addClass("selected");
            $(e).closest('.custom-select-container').find('input:hidden').val($(e).attr("rel"));
            $(e).closest('.custom-select-container').find('.selectbg span').html($(e).text());
        };

        var hide_options_wrapper = function () {
            $('.select-wrapper').slideUp(200, function (e) { $("div", this).closest('.custom-select-container').find('.selectbg').removeClass('active'); });
            $(document).unbind('keyup');
            $(document).unbind('keypress');
            $('body').unbind('click');
        };

        var show_options_wrapper = function (e) {
            var sender = e;
            hide_options_wrapper();
            if ($($selectitemswrapper).css('display') == 'none') {
                $($selectitemswrapper).slideDown(200);
                //$($selectitemswrapper).focus();
                $(this).addClass('active');
                e.stopPropagation();
                $(document).keypress(function (e) {
                    if (!e) e = window.event;
                    e.cancelBubble = true;
                    e.returnValue = false;
                    if (e.stopPropagation) {
                        e.stopPropagation();
                        e.preventDefault();
                    }
                });
                $(document).keyup(function (e) {

                    if (e.which == 40) {
                        var lastSelected = $($selectitemswrapper).find(".selected");
                        if (lastSelected.size() == 0) {
                            var nextSelected = $($optionswrapper).find("a:first:");
                        } else {
                            var nextSelected = lastSelected.next(".option-item");
                        }
                        if (nextSelected.size() == 1) {
                            update_select_value(nextSelected);
                            var rowOffset = (nextSelected.offset().top - $($selectitemswrapper).offset().top);
                            if (rowOffset > listheight) {
                                var value = parseInt($($optionswrapper).offset().top) - 19;
                                $($optionswrapper)[0].scrollTo(value);
                            }
                        }
                    } else if (e.which == 38) {
                        var lastSelected = $($selectitemswrapper).find(".selected");
                        var nextSelected = lastSelected.prev(".option-item");
                        if (nextSelected.size() == 1) {
                            update_select_value(nextSelected);
                            var rowOffset = (nextSelected.offset().top - $($selectitemswrapper).offset().top);
                            if (rowOffset > 0) {
                                $($optionswrapper)[0].scrollTo(($($optionswrapper).scrollTop() - 19) + "px");
                            }
                        }
                    } else if (e.which == 13 || e.which == 27) {
                        hide_options_wrapper();
                    }
                });
                $('.jScrollPaneTrack').click(function () { return false; });
                $('body').click(function () {
                    hide_options_wrapper();
                });
            } else {
                hide_options_wrapper();
            }
        };

        $.fn.clearItems = function () {
            var list = this;
            list.html("");
        };

        process_cascading_changes = function (controlid, valueid) {
            switch (controlid) {
                case "categorydd":
                    getproducts(valueid, "productdd");
                    break;
                case "productdd":
                    getproductpublications(valueid, "productpublicationdd");
                    break;
                case "productpublicationdd":
                    getpublicationissues(valueid, "publicationissuedd");
                    break;
                case "categorydd_iconselect":
                    getproducts(valueid, "productdd");
                    break;
                case "productdd_iconselect":
                    getproductpublications(valueid, "productpublicationdd");
                    break;
                case "productpublicationdd_iconselect":
                    getpublicationissues(valueid, "publicationissuedd");
                    break;
                case "footercategorydd":
                    getproducts(valueid, "footerproductdd");
                    break;
                case "footercategorydd_iconselect":
                    getproducts(valueid, "footerproductdd");
                    break;
            }
        }

        getproducts = function (sitemapid, target) {
            cleardropdown(target);
            cleardropdown("publicationdd");
            cleardropdown("publicationissuedd");
            setdropdowntext(target, "Loading...");
            $.getJSON("/ajax/GetProductsForSitemap/" + sitemapid, function (data) {
                $("#" + target + "_options").clearItems();
                $("#" + target + "_options").addItems(data);
                reinitialiseScrollPane("#" + target + "_options", true);
                setdropdowntext(target, "Select a service...");
            });
        };

        getproductpublications = function (productid, target) {
            cleardropdown(target);
            cleardropdown("publicationissuedd");
            setdropdowntext(target, "Loading...");
            $.getJSON("/ajax/GetProductPublications/" + productid, function (data) {
                $("#" + target + "_options").clearItems();
                $("#" + target + "_options").addItems(data);
                reinitialiseScrollPane("#" + target + "_options", true);
                setdropdowntext(target, "Select a publication...");
            });
        };

        getpublicationissues = function (publicationid, target) {
            cleardropdown(target);
            setdropdowntext(target, "Loading...");
            $.getJSON("/ajax/GetPublicationIssues/" + publicationid, function (data) {
                $("#" + target + "_options").clearItems();
                $("#" + target + "_options").addItems(data);
                reinitialiseScrollPane("#" + target + "_options", true);
                setdropdowntext(target, "Issue...");
            });
        };

        setdropdowntext = function (dropdown, text) {
            $("#" + dropdown + "_iconselect div.middlebg").html("<span>" + text + "</span>");
        };

        getdropdownvalue = function (dropdown) {
            var id = $("#" + dropdown + "_options .selected").attr("rel");
            if (typeof (id) == "undefined") {
                id = -1;
            }
            return id;
        };

        cleardropdown = function (dropdown) {
            $("#" + dropdown + "_options").clearItems();
            $("#" + dropdown + "_customselect").val(0);
            setdropdowntext(dropdown, "");
        };

        reinitialiseScrollPane = function (e, hideafterinit) {

            $(e).closest('.select-wrapper').show().addClass('active');
            $(e).height('auto');
            var newheight = $(e).height();
            if (newheight > listheight) {
                $(e).height(listheight);
                $(e).parent('.jScrollPaneContainer').height(listheight);
            }
            else {
                $(e).height(newheight);
                $(e).parent('.jScrollPaneContainer').height(newheight);
            }
            $(e).jScrollPane({ scrollbarMargin: 10, scrollbarWidth: 17, showArrows: true });
            if (hideafterinit) {
                //hide_options_wrapper();
                $(e).closest('.select-wrapper').hide().removeClass('active');
            }
        };

        // Wrap everthing up into this container
        var $container = $('<div></div>').addClass('custom-select-container');
        obj.wrap($container);

        // Find the selected option
        var $selectedoption = obj.find('option:selected');

        // Append the input to the container
        var $hidden = $('<input />').attr({ 'type': 'hidden', 'value': $selectedoption.val(), 'name': this.name, 'id': custom_select });
        obj.before($hidden);

        // Add the select wrapper
        var objborderwidth = parseInt(obj.css("borderLeftWidth"), 10) + parseInt(obj.css("borderRightWidth"), 10);

        if (isNaN(objborderwidth)) objborderwidth = 0;

        var $selectwrapper = $('<div></div>')
            .attr('id', id_icn_select).addClass('selectbg').width(obj.outerWidth()).addClass(obj.attr('class')).append(
                $('<div></div>').addClass('leftbg')).append(
                $('<div></div>').addClass('rightbg')).append(
                $('<div></div>').addClass('middlebg').append(
                    $('<span></span>').html($selectedoption.html())
                 )
             );

        // Add select items wrapper
        var $selectitemswrapper = $('<div></div>')
            .attr('id', id_holder).addClass('select-wrapper').addClass(obj.attr('class')).append(
                $('<div></div>').addClass('leftbg')).append(
                $('<div></div>').addClass('rightbg')
            );

        // Add the options wrapper
        var $optionswrapper = $('<div></div>').attr('id', id_slc_options).addClass('options-wrapper');
        $($optionswrapper).addItems(obj.find('option'));

        // Display custom select and remove select input
        obj.after($selectitemswrapper.append($optionswrapper)).after($selectwrapper).remove();

        // If the list is autosubmit remove the first blank item
        if ($selectitemswrapper.hasClass('autosubmit')) {
            if ($($optionswrapper).find('.option-item').first().attr('rel') == "") {
                $($optionswrapper).find('.option-item').first().remove();
            }
        }

        // Make the select wrapper same width as icn wrapper
        var borderwidth = parseInt($($selectitemswrapper).css("borderLeftWidth"), 10) + parseInt($($selectitemswrapper).css("borderRightWidth"), 10);
        if (isNaN(borderwidth)) borderwidth = 0;
        $($selectitemswrapper).css('width', $($selectwrapper).outerWidth() - borderwidth);

        // Add custom scroll bar
        reinitialiseScrollPane($optionswrapper, true);

        // Bind event handlers
        $selectwrapper.bind('click', show_options_wrapper);
        $selectitemswrapper.find('.option-item').bind('click', bind_optionitem_click);
    });
}
