// Patch for webkit/chrome
Request.HTML.implement({

	processHTML: function(text){
		var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
		text = (match) ? match[1] : text;
		
		var container = new Element('div');
		
		return $try(function(){
			var root = '<root>' + text + '</root>', doc;
			if (Browser.Engine.trident){
				doc = new ActiveXObject('Microsoft.XMLDOM');
				doc.async = false;
				doc.loadXML(root);
			} else {
				doc = new DOMParser().parseFromString(root, 'text/html');
			}
			root = doc.getElementsByTagName('root')[0];
			for (var i = 0, k = root.childNodes.length; i < k; i++){
				var child = Element.clone(root.childNodes[i], true, true);
				if (child) container.grab(child);
			}
			return container;
		}) || container.set('html', text);
	}

});
	
	
var SlideShow = new Class({
	Implements : [Events, Options],
	Extends: Fx,
	options : {
		delay			: 1000,
		duration		: 2000,	
		position		: 0,
		onInitialize	: $empty,
		onChange		: $empty,
		onMouseOver		: $empty,
		onMouseOut		: $empty,
		onPress			: $empty,
		onStart			: $empty,
		onComplete		: $empty
		},
	initialize : function(element, options) {
		this.setOptions(options);
		this.container = element;
		this.setChildren(this.container.getElements(this.container.getFirst().tagName));
		this.setPosition();
		this.options.init = !options.onInitialize ? $empty : options.onInitialize.bind(this);
		this.options.start = !options.onStart ? $empty : options.onStart.bind(this);
		this.options.mouseover = !options.onMouseOver ? $empty : options.onMouseOver.bind(this);
		this.options.mouseout = !options.onMouseOut ? $empty : options.onMouseOut.bind(this);
		this.options.click = !options.onPress ? $empty : options.onPress.bind(this)
		
		
		this.mouseoverEvent = function() {this.options.mouseover.run();}.bindWithEvent(this);
		this.mouseoutEvent = function() {this.options.mouseout.run();}.bindWithEvent(this);
		this.clickEvent = function() {this.options.click.run();}.bindWithEvent(this);
		
		this.children.addEvent("mouseover", this.mouseoverEvent);
		this.children.addEvent("mouseout", 	this.mouseoutEvent);	
		this.children.addEvent("click", 	this.clickEvent);
		
		this.intervalID = null;
		
		
		this.init();
		
		},
	setPosition : function () {
		this.currentIndex = 0;
		this.children.setStyle("opacity", 0);
		if(this.options.position == 0) {
			this.children[0].setStyle("opacity", 1);
			}
		else {
			if ($type(this.options.position) == "element") {
				for (var i = 0; i < this.children.length; ++i) {

					if(this.options.position == this.children[i]) {
						this.currentIndex = i;
						this.children[i].setStyle("opacity", 1);
						break;
						}
					this.children[i].setStyle("opacity", 0);
					}
				}
			else {
				this.children[this.options.position].setStyle("opacity", 1);
				}
			}
		this.position = this.currentIndex+1;
		},
	setChildren : function (items) {
		//if(this.children) this.children.setStyle("opacity", 1);
		this.children = items;
		//this.children.setStyle("opacity", 0);
		//this.children[0].setStyle("opacity", 1);
		//this.currentIndex = 0;
		this.count = this.children.length;
		},
	dispose : function () {
		this.stop();
		this.children.removeEvent("mouseover", this.mouseoverEvent);
		this.children.removeEvent("mouseout", 	this.mouseoutEvent);	
		this.children.removeEvent("click", 	this.clickEvent);
		this.children.setStyle("opacity", 1);
		this.children.setStyle("visibility", "visible");
		},
	init : function () {
		
		this.options.init.run()
		},
	start : function () {
		this.fireEvent("start");
		},
	mouseover : function () {
		this.options.mouseover.run()
		},
		
	click : function () {
		this.options.click.run()
		},
	complete : function () {
		this.fireEvent("complete");
		},
	play : function () {
		this.intervalID = this.next.periodical(this.options.delay, this)
		},
	
	stop : function () {
		$clear(this.intervalID);
		},
	
	next : function () {

		if (this.fxIn) {this.fxIn.cancel();}
		if (this.fxOut) {this.fxOut.cancel();}
		this.fadeOut();
		this.fadeIn();
		this.fireEvent("change");
		},
	goTo : function () {
		
		if (arguments[0] == this.position-1) return
		if (this.fxIn) {this.fxIn.cancel();}
		if (this.fxOut) {this.fxOut.cancel();}
		this.stop();
		this.fadeOut();
		this.currentIndex = arguments[0] == 0 ? this.children.length-1 : arguments[0]-1;
		this.position = this.currentIndex + 1;
		this.fadeIn()
		if(arguments.length == 2) {
			if(arguments[1]) {this.play();}
			}
		else {
			this.play();
			}
		},
	prev : function () {
		//alert(this.position)
		this.goTo(this.position-1 == 0 ? this.children.length-1 : this.position-2);
		},
	fadeIn : function () {

		this.currentIndex = this.currentIndex+1 == this.children.length ? 0 : ++this.currentIndex;
		this.position = this.currentIndex + 1;
		this.fxIn = new Fx.Morph(this.children[this.currentIndex], {
			duration : this.options.duration, 
			wait : false,
			onStart : function () {this.fireEvent("start")}.bind(this),
			onComplete : function () {this.fireEvent("complete")}.bind(this)
			}).start({"opacity": 1});
		},
			
	fadeOut : function () {
		this.fxOut = new Fx.Morph(this.children[this.currentIndex], {duration : this.options.duration, wait : false }).start({"opacity": 0});
		},
		
	getCount : function () {
		return this.count;
		},
	getPosition : function () {
		return this.position;
		},
	getItem : function () {
		return this.children[this.currentIndex];
		}
	});
	
	
	
/* ////////////////////////////////////////////////////////////////////
This class rotats elements top to bottom making the item of focus
full opacity and the others .1 opacity and transitions them through
//////////////////////////////////////////////////////////////////// */ 
var FeedRotator = new Class({
	Implements : [Events, Options],
	Extends: Fx,
	options : {
		delay			: 5000,
		duration		: 2000,	
		onInitialize	: $empty,
		onChange		: $empty,
		onMouseOver		: $empty,
		onMouseOut		: $empty,
		onPress			: $empty,
		onStart			: $empty,
		onComplete		: $empty
		},
	initialize : function(element, options) {
		this.setOptions(options);
		this.container = element;
		this.children = this.container.getElements(this.container.getFirst().tagName);
		
		if (this.children.length < 5) {
			do {
				for(var i = 0; i < this.children.length; ++i) {
					this.children[i].clone(true, true).inject(this.container);
					}
				this.children = this.container.getElements(this.container.getFirst().tagName);
				} 
			while (this.children.length < 5)
			}
		
		this.options.init = !options.onInitialize ? $empty : options.onInitialize.bind(this);
		this.options.start = !options.onStart ? $empty : options.onStart.bind(this);
		this.options.mouseover = !options.onMouseOver ? $empty : options.onMouseOver.bind(this);
		this.options.mouseout = !options.onMouseOut ? $empty : options.onMouseOut.bind(this);
		this.options.click = !options.onPress ? $empty : options.onPress.bind(this)
		
		
		this.children.addEvent("mouseover", function() {this.options.mouseover.run();}.bindWithEvent(this));
		this.children.addEvent("mouseout", 	function() {this.options.mouseout.run();}.bindWithEvent(this));	
		this.children.addEvent("click", 	function() {this.options.click.run();}.bindWithEvent(this));
		
		this.intervalID = null;
		this.currentIndex = 0;
		this.children.setStyle("opacity", .1);
		this.children[0].setStyle("opacity", 1);
		
		if (this.children.length < 5) {
			
			}
		
		this.init();
		
		},
	
	init : function () {
		this.container.setStyle("margin-top", (parseFloat(this.container.getParent().getStyle("height")) - this.children[this.currentIndex+1].getSize().y)/2);
		this.children.setOpacity(0);
		this.children[0].setOpacity(1)
		this.children[1].setOpacity(.1);
		this.options.init.run()
		},
	start : function () {
		this.fireEvent("start");
		},
	mouseover : function () {
		this.options.mouseover.run()
		},
		
	click : function () {
		this.options.click.run()
		},
	complete : function () {
		this.fireEvent("complete");
		},
	play : function () {
		this.intervalID = this.next.periodical(this.options.delay+this.options.duration, this)
		},
	
	stop : function () {
		//alert("");
		$clear(this.intervalID);
		},
	
	next : function () {
		if (this.fxIn) {this.fxIn.cancel();}
		if (this.fxOut) {this.fxOut.cancel();}
		new Fx.Morph(this.container, {
			duration : this.options.duration,
			wait: false,
			onStart : function () {
				//alert(this.currentIndex)
				new Fx.Morph(this.children[this.currentIndex], {duration:this.options.duration, wait:false}).start({"opacity":.1});
				new Fx.Morph(this.children[this.currentIndex+1], {duration:this.options.duration, wait:false}).start({"opacity":1});
				new Fx.Morph(this.children[this.currentIndex+2], {duration:this.options.duration, wait:false}).start({"opacity":[0,.1]});
				}.bind(this),
			onComplete : function () {
				
				if (this.currentIndex >= 2) {
					this.children[0].clone(true, true).cloneEvents(this.children[0]).inject(this.container);
					this.container.setStyle("margin-top", this.children[1].getCoordinates(this.container.getParent()).top)
					//this.container.setStyle("margin-top", parseFloat(this.container.getStyle("margin-top")) + (this.children[1].getSize().y/2))
					this.children[0].dispose();
					this.children = this.container.getElements("li");
					}
				else {
					++this.currentIndex;
					}
				}.bind(this)
			}).start({"margin-top": 
									parseFloat(this.container.getStyle("margin-top")) - 
									this.children[this.currentIndex+1].getCoordinates(this.container.getParent()).top + 
									(parseFloat(this.container.getParent().getStyle("height")) - this.children[this.currentIndex+1].getSize().y)/2
									});
		this.fireEvent("change");
		},
	
	getCount : function () {
		return this.count;
		},
	
	getItem : function () {
		return this.children[this.currentIndex];
		}
	});
	
	

var Mask = new Class({
	Implements : [Events, Options],
	Extends : Fx,
	options : {
		elementClass	: "",
		title 			: "",
		type 			: "",
		size			: "",
		url				: "",
		height			: null,
		buttons			: [],
		onInitialize	: $empty,
		onBeforeCreate	: $empty,
		onAfterCreate	: $empty,
		onBeforeDispose	: $empty,
		onAfterDispose	: $empty,
		onComplete		: $empty
		},
	initialize : function (options) {
		this.setOptions(options);
		this.options.init = !options.onInitialize ? $empty : options.onInitialize.bind(this);
		this.options.beforeCreate = !options.onBeforeCreate ? $empty : options.onBeforeCreate.bind(this);
		this.options.afterCreate = !options.onAfterCreate ? $empty : options.onAfterCreate.bind(this);
		this.options.beforeDispose = !options.onBeforeDispose ? $empty : options.onBeforeDispose.bind(this);
		this.options.afterDispose = !options.onAfterDispose ? $empty : options.onAfterDispose.bind(this);
		if(options.height != null) {
			this.options.height = options.height;
			}
		this.maskElement;
		this.titleElement;
		this.bodyElement;
		this.messageElement
		this.footerElement;
		this.containerHeight;
		this.resizeFx;
		this.resizeInt;
		this.urlRequest;
		this.init();
		
		window.addEvent("resize", function () {
			$clear(this.resizeInt);
			if($("site-mask")) {
				$("cover").setStyle("height" , window.getSize().y)
				$("site-mask").setStyle("height" , window.getSize().y)
				}
			  this.resizeInt = (function(){
					if ($("site-mask")) {
						this.resize();
						}
				  }).delay(400, this);
			
			}.bind(this));
		
		},
	init : function () {
		this.options.init.run()
		},
	create : function () {
		var blocks = {};
		this.options.beforeCreate.run();
		$(document.body).setStyle("overflow","hidden");
		blocks.mask 		= new Element("div", {"id":"site-mask", "class":this.options.elementClass});
		blocks.cover 		= new Element("div", {"id":"cover", "title" : "Click here to close this window"}).set("html", "&nbsp;").setOpacity(0.4).addEvent("click", function () {this.dispose();}.bind(this));
		blocks.container 	= new Element("div", {"id":"container"});
		blocks.title 		= new Element("h2").set("text", this.options.title);
		blocks.body 		= new Element("div", {"id":"mask-body"}).setStyles({"height":"25px"});
		blocks.message 		= new Element("div", {"id":"mask-message"}).set("html", "<p class=\"loading-indicator\">&nbsp;</p>");
		blocks.footer 		= new Element("div", {"id":"mask-footer"}).set("html", "<p>&nbsp;</p>");
		
		if (this.options.type != "") {
			blocks.mask.addClass(this.options.type);
			}
		
		this.maskElement 	= blocks.mask;
		this.titleElement	= blocks.title;
		this.bodyElement 	= blocks.body;
		this.messageElement = blocks.message;
		this.footerElement	= blocks.footer;
		
		if(this.options.size != "") {this.maskElement.addClass(this.options.size);}
		this.maskElement.setStyle("height", window.getScrollSize().y + "px");
		
		
		
		for(var b = 0; b < this.options.buttons.length; ++b) {
			if (!this.options.buttons[b].elementClass) {
				this.options.buttons[b].elementClass = "";
				}
			new Element("input", {"type":"button", "value": this.options.buttons[b].label, "id": this.options.buttons[b].id, "class":this.options.buttons[b].elementClass}).addEvent("click", function (ev, button) {
				if (button.label.toLowerCase() == "close" && !button.onClick) {
					this.dispose();
					}
				else if (button.label.toLowerCase() == "print" && !button.onClick) {
					print();
					}
				else {
					button.onClick.run(ev, this)
					}
				
				}.bindWithEvent(this, this.options.buttons[b])).inject(this.footerElement.getElement("p"));
			
			}
		this.maskElement.setStyle("top", window.getScroll().y + "px");
		
		blocks.message.inject(blocks.body);
		blocks.title.inject(blocks.container);
		blocks.message.inject(blocks.body);
		blocks.body.inject(blocks.container);
		blocks.footer.inject(blocks.container);
		blocks.cover.inject(this.maskElement);
		
		blocks.container.inject(this.maskElement);
		
		
		this.maskElement.injectInside(document.body);
		
		if (this.options.url != "") {
			this.loadURL(this.options.url)
			}
		this.options.afterCreate.run();
		return this;
		},
	dispose : function () {

		if(this.urlRequest) {
			this.urlRequest.cancel()
			}
		if (this.maskElement) {
			this.options.beforeDispose.run();
			var fx = new Fx.Morph(this.maskElement, {
				duration: 400, 
				wait: true,
				onComplete : function () {
					this.maskElement.dispose();
					$(document.body).setStyle("overflow","auto");
					this.options.afterCreate.run();
					}.bind(this)
				}).start({"opacity":0});
			}
		},
	setHTML : function (html) {
		this.getBodyElement().set("html", html);
		this.fireEvent("complete");
		return this;
		},
	getTitleElement : function() {
		return this.titleElement;
		},
	getBodyElement : function() {
		return this.messageElement;
		},
	getFooterElement : function() {
		return this.footerElement;
		},
	putMessage : function (html, type) {
		if (!type) type = "info";
		if(!$("mask-form-response")) {
			new Element("div", {"id":"mask-form-response", "class":type}).set("html", "<div id=\"response-body\">" + html + "</div>").inject(this.getBodyElement(), "top");
			}
		else {
			$("mask-form-response").set("class", type);
			$("response-body").set("html", html);
			}
		},
	setContainerHeight : function () {
		this.getBodyElement().setStyle("height", "auto");
		if (this.options.height) {
			this.containerHeight = this.options.height;
			}
		else {
			this.containerHeight = this.getBodyElement().getSize().y;
			}
		},
	resize : function () {
		var _fromTop = this.getBodyElement().getCoordinates().top;
		var _scrollTop = window.getScroll().y;
		var _winHeight = window.getSize().y
		var _containerHeight = this.containerHeight;
		var _availableHeight = _winHeight - (_fromTop - _scrollTop) - this.footerElement.getSize().y;
		var _targetHeight = Math.min(_containerHeight, _availableHeight);
		//console.debug(_winHeight +  "-  ( "+ _scrollTop + "-"+ _fromTop + ") -" + this.footerElement.getSize().y)
		//console.debug(_winHeight + " : " + _availableHeight)
		if ((_targetHeight != this.bodyElement.getSize().y || this.getBodyElement().getStyle("visibility") == "hidden")) {
			if (this.getBodyElement().getStyle("visibility") == "hidden") this.getBodyElement().setStyle("display","none");
			this.getBodyElement().setStyles({"overflow":"hidden"});
			this.resizeFx = new Fx.Morph(this.bodyElement, {
											wait:false, 
											duration:500,
											onComplete : function () {
												if (this.getBodyElement().getStyle("display") == "none") {
													this.getBodyElement().setStyle("display","block");
													var _fx = new Fx.Morph(this.getBodyElement(), {wait:false, duration:500}).start({opacity:[0,1]});
													}
												//if (_targetHeight < _containerHeight) {
													this.getBodyElement().setStyle("height", _targetHeight);
													this.getBodyElement().setStyles({"overflow":"auto"});
												//	}
												//this.resize.delay(3000, this);
												
												//this.resizeInt = this.resize.periodical(1000, this);
												}.bind(this)
											}).start({height:_targetHeight});
				
			
			}
		//alert(this.getBodyElement().getSize().y)
		},
	loadURL : function () {
		
		this.urlRequest = new Request.HTML({
					url: this.options.url,
					update : this.getBodyElement(),
					evalResponse  : true,
					onComplete : function (responseText) {
						//this.setHTML(responseText.toString())
						
						
						//this.resizeInt = this.resize.periodical(1000, this);
						this.fireEvent("complete");
						}.bind(this),
					onSuccess : function (responseText) {
						this.bodyElement.setStyles({"overflow":"hidden"});
						this.getBodyElement().setStyle("visibility","hidden");
						this.setContainerHeight();
						this.resize();
						//alert(responseText)
						//this.setHTML(responseText.toString())
						}.bind(this),
					onFailure : function (result) {	
					//for(p in result) alert(p)
						//alert(this.url);
						var _tmp = new Element("div").set("html", result.responseText).setStyle("display","none");
						//alert(_tmp.getElement("h2"));
						this.setHTML(_tmp.get("html"));
						this.maskElement.addClass("error");
						var h = this.getBodyElement().getElement("td[id=tableProps2]").get("text");
						var d = this.getBodyElement().getElement("td[id=tablePropsWidth]").get("text");
						_tmp.dispose();
						this.getBodyElement().setStyle("visibility","hidden");
						this.setHTML("<h3>Exception Occured</h3><p><strong>" + h + "</strong></p><p>" + d + "</p><p>URL : " + this.options.url + "</p>");
						this.setContainerHeight();
						this.resize();

						//this.resize();
						}.bind(this)
					}).send();
		}
	});

	

var SelectBox = new Class({
	Implements : [Events, Options],
	Extends : Fx,
	options : {
		elementClass	: "moo-select",
		onChange		: $empty,
		onClick			: $empty
		},
	initialize : function (element, options) {
		var liItem;
		if (!options) options = {};
		this.setOptions(options);
		this.element = element;
		if(!window.mooselectBaseIndex) {
			window.mooselectBaseIndex = 50000;
			window.mooSelects = [];
			}
		window.mooSelects.push(this);
		this.options.onchange = !options.onChange ? (function () {eval(this.element.getProperty("onchange"))}.bind(this)) : options.onChange.bind(this);
		this.isOpen = false;
		this.options.onclick = !options.onClick ? $empty : options.onClick.bind(this);
		this.optionElements = $(element).getChildren("option");
		this.value = "";
		this.text = "";
		
		for (var o = 0; o < this.optionElements.length; ++o) {
			var s = new Element("select")
			this.optionElements[o].clone().inject(s);
			if (s.get("html").indexOf('selected="selected"') != -1) {
				this.value = this.optionElements[o].value;
				this.text = this.optionElements[o].text;
				s.dispose();
				break;
				}
			s.dispose();	

			}
		
		
		
		
		// Build the container holding the UL that has the select options
		this.container = new Element("div", {"class": this.options.elementClass, "style":"z-index:" + --window.mooselectBaseIndex}).inject(element.getParent(), "top");
		this.container.setStyle("z-index", --window.mooselectBaseIndex);
		this.selUL = new Element("ul", {"class" : element.getProperty("class") == "" ? "moo-select-ul" : element.getProperty("class")});
		//this.selUL.setStyle("width", this.element.getSize().x);
		
		for (var o=0; o < this.optionElements.length; ++o) {
			var itemClass = (o == 0 ? "first" : (o == this.optionElements.length-1 ? "last" : ""))
			liItem = new Element("li", {"title":this.optionElements[o].text, "class":this.options.elementClass + "-option-idle "}).set("text", this.optionElements[o].text).inject(this.selUL);
			liItem.addClass( itemClass)
			//liItem.setStyle("width", this.element.getSize().x)
			
			liItem.addEvent("click", function (ev, item) {	
				this.element.options[item].selected = true;
				this.element.options[item].setProperty("selected", "selected")
				this.value = this.element.options[item].value;
				this.text = this.element.options[item].text;
				this.label.set("text", ev.target.get("text"));
				this.fx.toggle();
				this.options.onchange.run();
				}.bindWithEvent(this, o));
				
			liItem.optionFx = new Fx.Morph(liItem, {duration:200, wait:false});
			liItem.addEvent("mouseenter", function (ev) {
				//alert("." + this.options.elementClass + "-option-hover")
				//alert(ev.target)
				ev.target.optionFx.cancel();
				ev.target.optionFx.start("." + this.options.elementClass + "-option-hover");
				}.bindWithEvent(this));
			liItem.addEvent("mouseleave", function (ev) {
				ev.target.optionFx.cancel();
				ev.target.optionFx.start("." + this.options.elementClass + "-option-idle");
				}.bindWithEvent(this));
			
			}
		this.selUL.setStyle("visibility", "hidden");	
		this.selUL.inject(this.container, "top");
		this.fx = new Fx.Slide(this.selUL);
		this.element.setStyle("display", "none");
		/////////////////////////////////////////////////////////////
	
		// Build the link part of the select box that shows the selected option
		this.label = new Element("div", {"class":this.options.elementClass + "-label", "title":this.optionElements[0].text}).set("text", this.text == "" ? this.element.get("title") : this.text );
		this.label.addEvent("click", function () {
			for (var s=0; s < window.mooSelects.length; ++s) {
				if(window.mooSelects[s] != this && window.mooSelects[s].isOpen) {window.mooSelects[s].hide();}
				}
			if(this.isOpen) {this.hide()}
			else {this.show();}
			this.options.onclick.run();
			}.bindWithEvent(this));
		this.label.addEvent("mouseenter", function () {this.label.addClass(this.options.elementClass + "-label-hover");}.bindWithEvent(this));
		this.label.addEvent("mouseleave", function () {this.label.removeClass(this.options.elementClass + "-label-hover");}.bindWithEvent(this));
		this.label.inject(this.container, "top");
		this.hide();
		this.selUL.setStyle.delay(1000, this.selUL, ["visibility", "visible"]);	
		},
	show : function () {
		this.fx.toggle();
		this.isOpen = true;
		},
	hide : function () {
		this.fx.toggle();
		this.isOpen = false;
		}
	});	
	
	

var ArrayQue = new Class({
	Extends : Array,
	initialize : function (array) {
		this.array = array;
		this.index = 0;
		},
	next : function () {
		this.index = this.index == this.array.length-1 ? 0 : ++this.index;
		return this.array[this.index];
		},
	previous : function () {
		this.index = this.index == 0 ? this.array.length-1 : --this.index;
		return this.array[this.index];
		},
	get : function (type) {
		
		switch (type) {
			
			case "next" : {
				return this.next();
				}
			case "previous" : {
				return this.previous();
				}
			default : {
				return this.array[this.index];
				}
			}
		
		}
	});