document.hideAndShow = 'enabled';
document.visibilityRE = /visibility/i;

function showmenu(elem) {
	elem.className = "hover";
}

function hidemenu(elem) {
	elem.className = "";
}

function showClassedElements(elem, className, property) {
	if (document.hideAndShow != 'enabled') return;
	$(elem).select("." + className).each(function(elem){
		var style = elem.getAttribute('style');
		// IE6 returns an object with the DOM call getAttribute('style') so we must get text
		style = (typeof(style) == 'object' && style != null) ? style.cssText : style;
		if (document.visibilityRE.test(style)) {
			Element.setStyle(elem, {visibility: 'visible'});
		} else {
			Element.setStyle(elem, {display: ''});
		}
	});
}

function hideClassedElements(elem, className, property) {
	if (document.hideAndShow != 'enabled') return;
	$(elem).select("." + className).each(function(elem){
		var style = elem.getAttribute('style');
		// IE6 returns an object with the DOM call getAttribute('style') so we must get text
		style = (typeof(style) == 'object' && style != null) ? style.cssText : style;
		if (document.visibilityRE.test(style)) {
			Element.setStyle(elem, {visibility: 'hidden'});
		} else {
			Element.setStyle(elem, {display: 'none'});
		}
	});
}

function disableHideAndShow() {
	document.hideAndShow = 'disabled';
}

function enableHideAndShow() {
	document.hideAndShow = 'enabled';
}

// Legacy function; used in some quiz instructions!
function openNewWindow(URLtoOpen, windowName, windowFeatures) {
	newWindow=window.open(URLtoOpen, windowName, windowFeatures);
}

function openWindow(url, options) {
	var defaults = { width: 846, height: 710, toolbar: 'yes', resizable: 'yes', scrollbars: 'yes' };
	var options_string = $H(defaults).merge(options).map(function(pair){return pair.join("=");}).join(",");
	var newWindow = window.open(url, '_blank', options_string);
	newWindow.focus();
	return false;
}

var MultiColumnSortable = Class.create();
MultiColumnSortable.prototype = {
	initialize: function(element_id_array, size_array) {
		var options = Object.extend({
			handle:false,
			destroyAfterSort:false,
			tag:'div',
			format:/^[^_]*_(.*)$/
		}, arguments[2] || {});

		this.element_array = element_id_array.collect(function(id){ return $(id); });
		this.size_array = size_array;
		this.current_queued_requests = 0;
		this.options = options;

		for(i=0; i<this.element_array.length; i++) {
			// Initialize the Sortables
			Sortable.create(this.element_array[i].id, {
				constraint: '', 
				containment: this.element_array, 
				handle: options.handle,
				starteffect: new Function(),
				endeffect: new Function(),
				scroll: window,
				ghosting: false,
				revert: true,
				tag: options.tag,
				onUpdate: this._createUpdateFunction(this) });
		}
	},

	_createUpdateFunction: function(multiColumnSortable) {
		return function(element) {
			currentSequence = Sortable.sequence(element);
			if (currentSequence.length != multiColumnSortable.size_array[element.id.match(multiColumnSortable.options.format)[1]]) {
				// An item was dragged across columns; re-shuffle is required. We must make a note of this, 
				// and the last caller to check must trigger the action of updating and storing the order.
				if (multiColumnSortable.current_queued_requests == 0) {
					multiColumnSortable.current_queued_requests = 1;
				} else {
					multiColumnSortable.current_queued_requests = 0;
					multiColumnSortable.reshuffleLists();
					multiColumnSortable.sendUpdatedList();
				}
			} else {
				// Only one list was changed; just send the update.
				multiColumnSortable.sendUpdatedList();
			}
		}
	},

	reshuffleLists: function() {
		// Iterate pairwise through lists and adjust size to match the original list dimensions.
		for (i=0; i<this.element_array.length-1; i++) {

			var c = { col:this.element_array[i], s:Sortable.sortables[this.element_array[i].id] };
			var n = { col:this.element_array[i+1], s:Sortable.sortables[this.element_array[i+1].id] };

			if (Sortable.sequence(c.col).length > this.size_array[i]) {
				// Move an element from the bottom of the current column to the top of the next column
				var candidate = Sortable.findElements(c.col, c.s).last();
				n.col.insertBefore(candidate, Sortable.findElements(n.col, n.s).first());
			} else if (Sortable.sequence(c.col).length < this.size_array[i]) {
				// Move an element from the top of the next column to the bottom of the current column
				var candidate = Sortable.findElements(n.col, n.s).first();
				c.col.appendChild(candidate);
			} else {
				// Reshuffle may still contain columns that do not need to be adjusted
			}
		}
	},

	sendUpdatedList: function() {
		new Ajax.Request(this.options.url, { asynchronous:true, evalScripts:true, parameters:this.serialize() } );
		// After the list is re-sent, we should destory the Sortables if that options is set
		if (this.options.destroyAfterSort)
			this.element_array.each(function(element) {
				setTimeout(function() { Sortable.destroy(element) }, 0);
			});
	},

	serialize: function() {
		return this.element_array.collect(function(element) {
			return Sortable.serialize(element);
		}).join('&').replace(/_[^\[]*/g, "");
	}
}

// add a function to the queue of functions to be fun when the document is loaded:
function addLoadEvent(func) {
	var old_onload = window.onload;
	if (typeof window.onload != 'function'){
		window.onload = func;
	}else{
		window.onload = function(){
			old_onload();
			func();
		}
	}
}

function enhance_course_chooser(){
	$$('#course-switcher-form select').each(function(select){
		select.onchange = function(){
			this.form.submit();
		}
		select.style.width = (select.offsetWidth + 10) + "px";
	});
}

function enhance_grading_period_adding() {
	// Hide 'add grading period' form and instructions
	$('add-grading-period').hide();
	$('add-grading-period-instructions').hide();
	$('add-grading-period-submit').disable();

	$('grading-period').insert('<a href="#" id="add-grading-period-link" onclick="return false;">Add a grading period</a>');
	$('add-grading-period-link').observe('click', function(elem) {
		$('add-grading-period-submit').enable();
		$('grading-period').hide();
		$('add-grading-period').show();
		$('add-grading-period-instructions').show();
		if($('continue-link')) { $('continue-link').hide(); }
	});
}

function get_enclosing_form(elem) {
	var form = elem.parentNode;
	while(form != null && form.tagName != 'FORM') {
		form = form.parentNode;
	}
	return form;
}

function destroyAssignmentSortables() {
	if (window.chapterElements)	window.chapterElements.each(function(element) {	Sortable.destroy(element.id); });
}

function createAssignmentSortables() {
	window.chapterElements = $$("ul.chapter_elements");
	window.chapterElements.each(function(container) {
		var chapter_id = container.id.split('_')[1];
		var course_id  = container.id.split('_')[2];
		Sortable.create(container, {
			format:      /^(chapter_\d+_element_\d+_\d+)$/, 
			ghosting:    false, 
			constraint:  '',
			containment: window.chapterElements,
			handle:      'handle', 
			onUpdate:    sortableOnUpdate('/editor/courses/' + course_id + '/chapters/' + chapter_id + '/assignments/sort', { destroyAfterSort: true }),
			scroll:      window
		});
	});
}

function sortableOnUpdate(url, options) {
	return function(sortable) {
		new Ajax.Request(url, { asynchronous:true, evalScripts:true, parameters:Sortable.serialize(sortable) } );
		if (options["destroyAfterSort"]) {
			Sortable.destroy(sortable);
		}
	}
}
