jQuery.SelectControl = {
    // CSS class constants
    SELECT_DISABLED_CLASS : 'selectDisabledClass',
    SELECT_CLASS : 'selectClass',

    OPTION_CLASS : 'optionClass',
    SELECTED_OPTION_CLASS : 'optionClassSelected', 
    SELECTED_OPTION_SUFFIX : 'Selected',
    OPTION_DISABLED_CLASS : 'optionDisabledClass',

    SELECT_TEMPLATE : '<div id="{name}Div">' +
                      '    <input type="hidden" id="{name}" value="">' +
                      '    <ul>' +
                      '        <li>' +
                      '            <a  id="{name}Display" class="{disabled}" style="-moz-user-select:none;" onselectstart="return false;"></a>' +
                      '	           <ul id="{name}Options" class="optionsContainer" style="display:none;"></ul>' +
                      '	       </li>' +
                      '    </ul>' +
                      '</div>',
    OPTION_TEMPLATE : '<li>' +
                      '    <a id="{name}{value}" class="{state}" style="-moz-user-select: none;" onselectstart="return false;">{label}</a>' +
                      '</li>'
};

jQuery.fn.SelectControl = function(name,params) {
    /*
    * name: select id
    * params: {
    *    disabled: disable/enable select
    *    onchange: onchange function
    *    options: array of options e.g. [ {label: 'choose', value: 0, disabled: true},
    *                                     {label: 'option 1', value: 1},
    *                                     {label: 'option 2', value: 2, selected: true},
    *                                     {label: 'option 3', value: 3}]
    }
    * */

    var settings = {
       disabled: false,
       onchange: null,
       options: null
    }

    if (params) {
       jQuery.extend(settings,params);
    }

    var select = jQuery.SelectControl.SELECT_TEMPLATE;

    // replace name
    select = select.replace(/{name}/g,name);

    // replace disabled
    if (settings.disabled) {
       select = select.replace(/{disabled}/g,jQuery.SelectControl.SELECT_DISABLED_CLASS);
    } else {
       select = select.replace(/{disabled}/g,jQuery.SelectControl.SELECT_CLASS);
    }

    jQuery(select).appendTo(this);

    jQuery('#' + name).each(function() {
        // add onClick listener to toggle options
        jQuery('#' + name + 'Display').click(function() {
            //jQuery('../../../input',this).toggleOptions();
			jQuery(this).find("../../../input").toggleOptions();
        });
    });

    // add onchange
    if (settings.onchange) {
        jQuery('#' + name).change(function() {
            settings.onchange();
        });
    }

    if (settings.options) {
        jQuery('#' + name,this).setOptions(settings.options);
    }

    return this;
}

jQuery.fn.enableSelectControl = function() {
    //return jQuery('../ul/li/a[@class="' + jQuery.SelectControl.SELECT_DISABLED_CLASS + '"]',this).each(function() {
	return jQuery(this).find('../ul/li/a[@class="' + jQuery.SelectControl.SELECT_DISABLED_CLASS + '"]').each(function() {
        this.className = jQuery.SelectControl.SELECT_CLASS;
    });
}

jQuery.fn.disableSelectControl = function() {
    //return jQuery('../ul/li/a[@class="' + jQuery.SelectControl.SELECT_CLASS + '"]',this).each(function() {
	return jQuery(this).find('../ul/li/a[@class="' + jQuery.SelectControl.SELECT_CLASS + '"]').each(function() {
        this.className = jQuery.SelectControl.SELECT_DISABLED_CLASS;
    });
}

jQuery.fn.closeSelectControl = function() {
	//return jQuery('../ul/li/a[@class="' + jQuery.SelectControl.SELECT_CLASS + '"]',this).each(function() {
    return jQuery(this).find('../ul/li/a[@class="' + jQuery.SelectControl.SELECT_CLASS + '"]').each(function() {
        //jQuery('../ul',this).each(function() {
		jQuery(this).find('../ul').each(function() {
            if (this.style.display == 'block') {
                // this will reset z-indexes
                ie_apply_zindex_undo();
                this.style.display = 'none';
            }
        });
    });
}

jQuery.fn.toggleOptions = function() {
	//return jQuery('../ul/li/a[@class="' + jQuery.SelectControl.SELECT_CLASS + '"]',this).each(function() {
    return jQuery(this).find('../ul/li/a[@class="' + jQuery.SelectControl.SELECT_CLASS + '"]').each(function() {
        //jQuery('../ul',this).each(function() {
		jQuery(this).find('../ul').each(function() {
            if (this.style.display != 'block') {
                // ie hack to display over all elements on the page
                ie_apply_zindex($(this), 5);
                this.style.display = 'block';
            } else {
                // this will reset z-indexes
                ie_apply_zindex_undo();
                this.style.display = 'none';
            }
        });
    });
}

jQuery.fn.selectOption = function(value) {
	
    var currentOption = jQuery('#' + this.get(0).id + this.get(0).value);
    var newOption = jQuery('#' + this.get(0).id + value);

    // switch selected option styles
    if (newOption.length > 0 &&
        newOption.get(0).className != jQuery.SelectControl.OPTION_DISABLED_CLASS) {

        // get class and toggle state of current selected option
        if (currentOption.length > 0 &&
            currentOption.get(0).className != jQuery.SelectControl.OPTION_DISABLED_CLASS) {

            // get currently selected class and set state as unselected
            var currentClassName = currentOption.get(0).className;
            currentOption.get(0).className = currentClassName.replace(jQuery.SelectControl.SELECTED_OPTION_SUFFIX,'');
        }

        // get class and toggle selected state of new option
        var newClassName = newOption.get(0).className;

        if (!newClassName.match(jQuery.SelectControl.SELECTED_OPTION_SUFFIX)) {
            newOption.get(0).className = newClassName + jQuery.SelectControl.SELECTED_OPTION_SUFFIX;
        }
    }

    // set value
    this.val(value);

    //var displayValue = jQuery('../ul/li/ul/li/a#' + this.get(0).id + value,this);
	var displayValue = jQuery(this).find('../ul/li/ul/li/a#' + this.get(0).id + value);

    // set display label
    //jQuery('../ul/li/a',this).empty().append(displayValue.text());
	jQuery(this).find('../ul/li/a').empty().append(displayValue.text());

    // call on change callback function
    if (jQuery('#' + this.get(0).id + value).get(0).className != jQuery.SelectControl.OPTION_DISABLED_CLASS) {
        this.change();
    }
    
    return this;
}

jQuery.fn.removeOption = function(value) {
    //var option = jQuery('..',jQuery('#' + this.get(0).id + value));
	var option = jQuery('#' + this.get(0).id + value).parent();
    return option.remove();
}

jQuery.fn.removeOptions = function() {
    //jQuery('../ul/li/ul.optionsContainer',this).empty()
	jQuery(this).find('../ul/li/ul.optionsContainer').empty()

    return this;
}

jQuery.fn.setOptions = function(options) {
    
    this.removeOptions();
	
    if (options) {
		
        var optionString = '';
		
        var selectedValue;
		
        for (var i = 0; i < options.length; i++) {
            var option = jQuery.SelectControl.OPTION_TEMPLATE.replace(/{label}/g,options[i].label);
            option = option.replace(/{value}/g,options[i].value);
            option = option.replace(/{name}/g,this.get(0).id);
			
            if (options[i].disabled) {
                option = option.replace(/{state}/g,jQuery.SelectControl.OPTION_DISABLED_CLASS);
            } else {
                if (options[i].selected) {
                    if (!selectedValue) {
                        selectedValue = options[i].value;
                    }
                    option = option.replace(/{state}/g,(options[i].style ? options[i].style + jQuery.SelectControl.SELECTED_OPTION_SUFFIX : jQuery.SelectControl.SELECTED_OPTION_CLASS));
                } else {
                    option = option.replace(/{state}/g,(options[i].style ? options[i].style : jQuery.SelectControl.OPTION_CLASS));
                }
            }
            optionString += option;
        }
		
        if (!selectedValue) {
            selectedValue = options[0].value;
        }
		
        //jQuery('../ul/li/ul.optionsContainer',this).append(optionString);
		jQuery(this).find('../ul/li/ul.optionsContainer').append(optionString);
    }
	
    // add onClick listener to toggle options and select option
    //jQuery('../ul/li/ul/li/a',this).each(function() {
	jQuery(this).find('../ul/li/ul/li/a').each(function() {
        if (this.className != jQuery.SelectControl.OPTION_DISABLED_CLASS) {
            jQuery(this).click(function() {
                //jQuery('../../../../../input',this).selectOption(this.id.replace(jQuery('../../../../../input',this).get(0).id,'')).toggleOptions();
				jQuery(this).find('../../../../../input').selectOption(this.id.replace(jQuery(this).find('../../../../../input').get(0).id,'')).toggleOptions();
            });
        }
    });

    return this.selectOption(selectedValue);
}



var iaz_preserved_elements = [];

function ie_apply_zindex(element, zindex, context) {
	// default values
	if (undefined == zindex) {
		var zindex = 1;
	}
	if (undefined == context) {
		var context = $("body");
	}

	// undo past ie_apply_zindex()
	for (i = iaz_preserved_elements.length-1; i >= 0; i--) {
		iaz_preserved_elements[i].css("z-index", 0);
	}
	iaz_preserved_elements = [];

	// find relative-positioned ancestors of element within context
	element.parents().each(function (index, element) {
		var ancestor = $(element);
		if ("relative" == ancestor.css("position")) {
			// preserve ancestor's current z-index
			iaz_preserved_elements.push(ancestor);
			
			// apply z-index to ancestor
			ancestor.css("z-index", zindex);
		}
		if (ancestor == context) {
			return false;
		}
	});
}

function ie_apply_zindex_undo() {
	for (i = iaz_preserved_elements.length-1; i >= 0; i--) {
		iaz_preserved_elements[i].css("z-index", 0);
	}
	iaz_preserved_elements = [];
}

