
(function(){

//mixture of YUI, prototype, jQuery.  

if(	typeof YAHOO == undefined || 
	YAHOO.util.Dom == undefined || 
	YAHOO.util.Event == undefined || 
	YAHOO.util.Selector == undefined)
	throw "YAHOO or YAHOO.util.Dom or Yahoo.util.Event or YAHOO.util.Selector is not defined" +
	" make sure yahoo-dom-event.js and yahoo-selector-beta is included before moodle.js";
	
var Y =  YAHOO,
	window = this,
	undefined,
	Moodle = window.Moodle = window.$ = function(query, root) {
		return new Moodle.ext.init(query, root);
	},
	$$ = function(element) {
		return new Moodle.ext.init(element.nodeType ? element : document.getElementById(element));
	},
	_$ = window.$,
	$m = window.$,
	d = Y.util.Dom;
	
	Array.prototype.toHash = function() {
		var hash = {};
		for(var i=0; i < this.length; i++)
			hash[this[i]] = this[i];
	}
	
	Array.prototype.each = function(callback, context) {
		for(var i =0; i < this.length; i++) 
			callback.apply(context, [this[i], i]);
	}	
	
	var extend = function(target, source, properties){
		properties = properties || source;
		for(var property in properties)
			target[property] = source[property];
	}
	
	var collect = function(element, property) {
		var elements = [];
   		while (element = element[property])
   		{
      		if (element.nodeType == 1)
        		elements.push(element);
    	}
    	return elements;
	}
	
	var collectOnce = function(element, property)
	{
		while(element = element[property])
			if(element.nodeType == 1)
				return element;
	}
	
	extend(Moodle, Y.lang);
	extend(Moodle.env = {}, Y.env.ua);

	Moodle.DOMReadyEvent = YAHOO.util.Event.DOMReadyEvent;
	Moodle.ready = YAHOO.util.Event.onDOMReady;
	Moodle.cssPrefix = "moodle-";
	Moodle.log = Y.log;

Moodle.ext = Moodle.prototype =  {
	selector: null,
	init: function(query, root) {
		if(query.nodeType)
			this.elements = [query];
		else if(Moodle.isArray(query))
			this.elements =  query;
		else if(Moodle.isString(query))  {
			this.selector = query;
			this.elements =  Y.util.Selector.query(query, root);
		} else 
			this.elements = [];
		this.length = this.elements.length;
		return this;
	},
	
	size: function() {
		return this.length;
	},
	
	empty: function() {
		this.elements = [];
		this.length = 0;
		return this;
	},
	
	each: function(callback, args, context) {
		var stack = args || [];
		context = context || this;
		stack.unshift(this.elements[0]);
		for(var i = 0; i < this.length; i++) {
			stack[0] = this.elements[i];				
			callback.apply(context, stack);
		}
	},
	
	invoke: function(callback, args, context) {
		var results = [], stack = args || [], context = context || this;
		stack.unshift(this.elements[0]);
		for(var i = 0; i < this.length; i++) {
			stack[0] = this.elements[i];
			results.push(callback.apply(context, stack));
		}
		if(results.length == 1)
			return results[0];
		return results;
	},
	
	css: function() {
		if(arguments.length == 0)
			return this.elements[0].style;
		
		if(arguments.length == 2) {
			this.each(d.setStyle, arguments);
			return this;
		}
		
		style = arguments[0];
		
		if(Moodle.isObject(style))
		{
			for(var property in style)
				this.each(d.setStyle, [property, style[property]]);
			return this;
		} 
		
		return this.invoke(d.getStyle, [style]);
	},
	
	addClass: function(className) {
		this.each(d.addClass, [className]);
		return this;
	},
	
	removeClass: function(className) {
		this.each(d.removeClass, [className]);
		return this;
	},
	
	hasClass: function(className) {
		var el = this.elements[0], names = el.className.split(" ");
		for(var i = 0; i < names.length; i++)
			if(names[i].toLowerCase() == className.toLowerCase())
				return true;
		return false;
	},
	
	on: function(eventName, callback, context) {
		context = context || this;
		this.each(Y.util.Event.addListener, [eventName, callback, context], Y.util.Event);
		return this;
	},
	
	replaceClass: function(oldClass, newClass) {
		this.each(d.replaceClass, [oldClass, newClass]);
		return this;
	},
	
	toggleClass: function(className) {
		if(this.hasClass(className))
			this.removeClass(className);
		else 
			this.addClass(className);
		return this;
	},
	
	show: function(attributes) {
		if(attributes && YAHOO.util.Anim)
		{
			this.each(function(item){
				var anim = new YAHOO.util.Anim(item, attributes);
				anim.animate();
			});
		} else {
			this.each(function(item) {
				item.style.display = "";
			});
		}
		return this;	
	},
	
	hide: function(attributes) {
		if(attributes && YAHOO.util.Anim)
		{
			this.each(function(item){
				var anim = new YAHOO.util.Anim(item, attributes);
				anim.animate();
			});
		} else {
			this.each(function(item) {
				item.style.display = "none";
			});
		}
		return this;	
	},
	
	toggle: function() {
		this.each(function(item) {
			if(item.style.display = "")
				item.style.display = "none";
			else 
				item.style.display = "";	
			});
	},
	
	get: function(index) {
		if(index != null)
			return this.elements[index];
		return this.elements[0];
	},
	
	up: function() {
		if(arguments.length == 0)
			return Moodle(this.invoke(
			function(item){ 
				return item.parentNode;
			}));
	},
	
	down: function() {
		if(arguments.length == 0)
			return Moodle(this.invoke(
				function(item){
					el = item.firstChild;
    				while (el && el.nodeType != 1) el = el.nextSibling;
    				return el;
				}));
	},
	
	next: function() {
		if(arguments.length == 0)
			return Moodle(this.invoke(
				function(item) {
					return collectOnce(item, "nextSibling");
				}
			));
	},
	
	previous: function() {
		if(arguments.length == 0)
			return Moodle(this.invoke(
				function(item) {
					return collectOnce(item, "previousSibling");
				}
			));
	}
};

(function() {
var onEvents = ("blur,focus,load,resize,scroll,unload,click,dblclick," +
	"mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
	"change,select,submit,keydown,keypress,keyup,error").split(",");
	
for(var i = 0; i < onEvents.length; i++) {
	var ev = onEvents[i];
	(function(eventName) {
		Moodle.prototype[eventName] = function(fn, context) {
			this.on(eventName, fn, context);
		}
	})(ev);
}

})();

Moodle.ext.init.prototype = Moodle.prototype;

Moodle.extend = Moodle.ext.extend = function(source, context, properties) {
	extend(context || Moodle.prototype, source, properties);
}


Moodle.ui = {
	create: function(source) {
		function klass() {
  			this.init.apply(this, arguments);
		}
		
		extend(klass.prototype, Moodle.ui.Control.prototype);
		extend(klass.prototype, source);
			
		klass.prototype.constructor = klass;
		
		return klass;
	},
	Control: function(query, options) {
		this.init.call(query, options);
	}
}

Moodle.ui.Control.prototype = {
	query: null,
	hideAttributes: null,
	showAttributes: null,
	init: function(query, options) {
		this.query = $(query);
		extend(this, options);
		this.load();	
	},
	load: function() {
		
	},
	hide: function() {
		this.query.hide(this.hideAttributes);
	},
	show: function(){
		this.query.show(this.showAttributes);
	},
	toggle: function() {
		if(this.query.get().style.display == "none")
			this.show();
		else 
			this.hide();
	}
}

//create shortcuts for yui widgets. 
Moodle.ready(function() {
	var w = Y.widget, yuiWidgets = [], widgets = {}, shortcuts = {}, $ = Moodle;
	Moodle.yui = {};
	
	var body = $("body").addClass("yui-skin-sam");
	if(document.getElementById("layout-table") == null)
		body.addClass("no-layout-table");

	for(var yuiWidget in w)
		if(yuiWidget.indexOf("DS_") == -1)
			yuiWidgets.push(yuiWidget);

	yuiWidgets.each(function(item) {
		Moodle[item.toLowerCase()] = function(element, options, events) {
			options = options || {};
			altName = element.id || element;
			events = events || {};
		
			var widget = new w[item](element, options);
			//element[item.toLowerCase()] = widget;
			for(var e in events)
				widget[e].subscribe(events[e], widget);
			
			if(options.render) 
				widget.render();
		}
		
		shortcuts[item.toLowerCase()] = function(options, events, altName) {
			this.each(function(element) {
				Moodles[item.toLowerCase()](element, options, events, altName);
			});
		}
		
	});
	
	Moodle.extend(shortcuts);
	
});

if(!Y.util.Cookie)
	throw new "Y.util.Cookie needs to be loaded";

Moodle.Cookie = Y.util.Cookie;

	(function() {
		var p = Moodle.cssPrefix,
			collapsed = p + "block-collapsed",
			c = Moodle.Cookie;
			$ = Moodle;
			
		var cookie = c.get(p + "blocks");
		
		if(cookie == null)
			c.set(p + "blocks", "the blocks state");
		
		Moodle.ui.Block = Moodle.ui.create({
			
		});
		
		Moodle.ui.Block.toggle = function(block, element,  e) {
			if(e)
				YAHOO.util.Event.stopEvent(e);
			$(block).toggleClass(collapsed);
			if(element.innerHTML.indexOf('hide') > -1)
				element.innerHTML.replace('hide', 'show');
			else 
				element.innerHTML.replace('show', 'hide');
			
			c.setSub(p + "blocks", block + "-collapsed", $(block).hasClass(collapsed));
			return false;
		}
	})();
	
extend(Moodle.json = {}, Y.lang.JSON);

Moodle.json.rpc = {
	request: function(serviceUrl, action, args, callback){
		var requestMsgObj = {
	       "action": action,
	       "args": args
		},
		json = Moodle.json,
		requestMsgJson = json.stringify(requestMsgObj); 
		escapedRequestMsgJson = escape(requestMsgJson);	
	
		YAHOO.util.Connect.asyncRequest(
			'POST', 
			serviceUrl,  {
				success: function(o) {
					var response = null;
				
					try {
					 	if (o.status == 200 && o.responseText != null) 
							response = json.parse(o.responseText);                          
		 				else 
		 				{
		 					response = {
								success: false,
		 						error: { message: "<span class='error'>Unknown error - <span class='status'>" + 
		 							o.status + "</span> - <span class='response'>" + o.responseText + "</span></span>" 
	 							}
							};
						}
					} catch (ex) {
						response = {
							success: false,
							error: { message: ex.message }
	                    };
					}							
					
					callback(response);
				},
			 
			    failure: function(o) {		    	
			    	var response = null;
							
					response = {
						success: false,
						error: { message:"<span class='error'>Unknown error - <span class='status'>" + 
		 							o.status + "</span> - <span class='response'>" + o.responseText + "</span></span>" 			
	 					}
					};			
					
					callback(response);
			    }		     		    
			}, 
			"msg=" + escapedRequestMsgJson);
	}
}
		
})();