var Util = {
	version: '0.1b Beta',
	
	/* From www.prototypejs.org */
	Browser: {
			IE:     !!(window.attachEvent && !window.opera),
			Opera:  !!window.opera,
			WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
			Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
	},
	/* From www.prototypejs.org */
	BrowserFeatures: {
			ElementExtensions: !!window.HTMLElement,
			SpecificElementExtensions:
				(document.createElement('div').__proto__ !==
				 document.createElement('form').__proto__)
	},

	Image: {
		over: '_ovr',
		pngClassName: 'png',
		noImagem: 'images/noimage.gif'
	}
};

/* Functions */
function $(element) {
  if (typeof element == 'string'){
    element = document.getElementById(element);
  }
  return Element.extend(element);
}

function $A(iterable) {
  if (!iterable) { return []; }
  if (iterable.toArray) {
  	return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++){
      results.push(iterable[i]);
	}
    return results;
  }
}

function $C(element, nParent) {
	var parent = $(nParent);
	parent = Object.isElement(parent) ? parent : document;
	return $(parent.createElement(element));
}

function var_dump(iterator, nLevel) {
	var text = "";
	var padding = "";
	var level = nLevel || 0;
	var i = 0;

	for(i = 0; i < (level + 1); i++) {
		padding += "    ";
	}

	if(typeof iterator == 'object') {
		for(i in iterator) {
			var value = iterator[i];

			if(typeof(value) == 'object') {
				text += padding + '\"' + i + '\"... \n';
				text += var_dump(value, level+1);
			} else {
				text += padding + '\"' + i + '\" => \"' + value + '\"\n';
			}
		}
	}
	return  text;
}

/* Object Function */
Object.extend = function(destination, source) {
  for (var property in source) {
    destination[property] = source[property];
  }
  return destination;
};

document.getElementsByClassName = function(className) {
	var nodes = document.getElementsByTagName('*');
	var elements = Array();

	for (var i in nodes) {
		if (nodes[i].className) {
			if (
				(nodes[i].className.search(className + ' ') > -1) ||
				(nodes[i].className.search(' ' + className + ' ') > -1) ||
				(nodes[i].className.search(' ' + className) > -1) ||
				(nodes[i].className == className)
			) { elements[elements.length] = $(nodes[i]); }
		}
	}

	return elements || [];
};

/*
* Class (prototype)
*
* Prototype.js 
* From: www.prototypejs.org
*
* Based on Alex Arnell's inheritance implementation.
*/
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    };
  }
};

/*
* Extended Object (prototype)
*
* Prototype.js 
* From: www.prototypejs.org
*
*/
Object.extend(Object, {
  isElement: function(object) {
    return object && object.nodeType == 1;
  },

  isArray: function(object) {
    return object && object.constructor === Array;
  },

  isFunction: function(object) {
    return typeof object == "function";
  },

  isString: function(object) {
    return typeof object == "string";
  },

  isNumber: function(object) {
    return typeof object == "number";
  },

  isUndefined: function(object) {
    return typeof object == "undefined";
  }
});

/*
* Element Functions (prototype)
*
* Prototype.js 
* From: www.prototypejs.org
*/
if (!window.Element) { 
	var Element = {};
}

/* Element Functions (util) */
Element.Methods = {
  removeClassName: function(element, className) {
    if (!(element = $(element))) { return; }
    element.className = element.className.replace(
      new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
    return element;
  },

	addAlphaImageLoader: function(element, src) {
		if (!Util.Browser.IE) { return undefined; }

		element.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='"+src+"')";
		return element;
	},

	hidden: function(element) {
		element.style.visibility = 'hidden';
		return element;
	},

	visible: function(element) {
		element.style.visibility = 'visible';
		return element;
	}
};

Element.extend = function(element) {
  var F = Util.BrowserFeatures;
  if (!element || !element.tagName || element.nodeType == 3 ||
   element._extended || F.SpecificElementExtensions || element == window)
    { return element; }

  var methods = {}, tagName = element.tagName, cache = Element.extend.cache,
   T = Element.Methods.ByTag;

  // extend methods for all tags (Safari doesn't need this)
  if (!F.ElementExtensions) {
    Object.extend(methods, Element.Methods);
    Object.extend(methods, Element.Methods.Simulated);
  }

  // extend methods for specific tags
  if (T[tagName]) { Object.extend(methods, T[tagName]); }

  for (var property in methods) {
    var value = methods[property];
    if (typeof value == 'function' && !(property in element)) {
      element[property] = cache.findOrStore(value);
	}
  }

  element._extended = Util.emptyFunction;
  return element;
};

Element.extend.cache = {
  findOrStore: function(value) {
    return (this[value]= this[value] || function() {
      return value.apply(null, [this].concat($A(arguments)));
    });
  }
};

Object.extend(Element.Methods, {
  childOf: Element.Methods.descendantOf,
  childElements: Element.Methods.immediateDescendants
});

Element.Methods.ByTag = { };
Object.extend(Element, Element.Methods);

Element.addMethods = function(methods) {
  var F = Util.BrowserFeatures, T = Element.Methods.ByTag;

	if (!methods) {
    /* Object.extend(Form, Form.Methods); */
    /* Object.extend(Form.Element, Form.Element.Methods); */
  }

  if (arguments.length == 2) {
    var tagName = methods;
    methods = arguments[1];
  }

  if (!tagName) { Object.extend(Element.Methods, methods || {});
  } else {
    if (tagName.constructor == Array) { tagName.each(extend);
    } else { extend(tagName); }
  }

  function extend(tagName) {
    tagName = tagName.toUpperCase();
    if (!Element.Methods.ByTag[tagName]){ 
      Element.Methods.ByTag[tagName] = {};
	}
    Object.extend(Element.Methods.ByTag[tagName], methods);
  }

  function copy(methods, destination, onlyIfAbsent) {
    onlyIfAbsent = onlyIfAbsent || false;
    var cache = Element.extend.cache;
    for (var property in methods) {
      var value = methods[property];
      if (!onlyIfAbsent || !(property in destination)) {
        destination[property] = cache.findOrStore(value);
	  }
    }
  }

  function findDOMClass(tagName) {
    var klass;
    var trans = {
      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
      "FrameSet", "IFRAME": "IFrame"
    };
    if (trans[tagName]) { klass = 'HTML' + trans[tagName] + 'Element'; }
    if (window[klass]) { return window[klass]; }
    klass = 'HTML' + tagName + 'Element';
    if (window[klass]) { return window[klass]; }
    klass = 'HTML' + tagName + 'Element';
    if (window[klass]) { return window[klass]; }

    window[klass] = {};
    window[klass].prototype = document.createElement(tagName).__proto__;
    return window[klass];
  }

  if (F.ElementExtensions) {
    copy(Element.Methods, HTMLElement.prototype);
    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
  }

  if (F.SpecificElementExtensions) {
    for (var tag in Element.Methods.ByTag) {
      var klass = findDOMClass(tag);
      if (Object.isUndefined(klass)) { continue; }
      copy(T[tag], klass.prototype);
    }
  }

  Object.extend(Element, Element.Methods);
  delete Element.ByTag;
};

var Toggle = { display: Element.toggle };

Object.extend(String.prototype, {
	strip: function() {
    return this.replace(/^\s+/, '').replace(/\s+$/, '');
  }
});

Object.extend(Number.prototype, {
	format: function (num) {
		var newNum = this.toString();
		while(newNum.length < num) {
			newNum = '0' + newNum;
		}
		return newNum;
	}
});

/* Utils ******************************************************************************************** */

/* Style */
var Style = {
	create: function(iterator) {
		var style = $C("style");
		var sheets = document.styleSheets;
		style.type = "text/css";
		style.media = "all";

		document.getElementsByTagName("head")[0].appendChild(style);

		for (var i in iterator) {
			sheets[sheets.length - 1].addRule(i, iterator[i]);
		}
	},
	
	remove: function(definition, identify) {
		if (!definition) { return false; }
		var iterator = iterator || {};
		var styleSheets = document.styleSheets;

		for (var i in styleSheets) {
			var sheets = styleSheets[i];

			if (typeof sheets == 'object') {
				for (var j in sheets.rules) {
					var rules = sheets.rules[j];

					if (typeof rules == 'object') {
						var style = rules.style;
						var selector = rules.selectorText;

						if (typeof style == 'object' && (selector.search(identify) > -1 || !identify)) {
							for (var text in style) {
								if (text == definition && style[text] !== '') {
									style[text] = '';
								}
							}
						}
					}
				}
			}
		}
	}
};

/* Image */
var Images = {};

Object.extend(Images, {
	preLoad: function(images) {
		if (!images) { return false; }
		if (!Object.isArray(images)) { images = [images]; }
		
		var img = $C("img");
		for(var image in images){
			img.src = images[image];
		}
		delete img;
	},
	
	fixPngForIe: function() {
		var elements = document.getElementsByClassName(Util.Image.pngClassName);

		var backgroundPattern = /background-image:\s*url\(([\"\']?)([^\)]+\.png)\1\)/i;
		var imagePattern = /<(input|img)[^>]*src=([\"\']?)([^>]*\.png)\2[^>]*>/i;
		var backgroundPatternSimple = /url\(([\"\']?)([^\)]+\.png)\1\)/i;

		for (var i in elements) {
			var element = elements[i];
			var outer = element.outerHTML;

			var matchBackground = outer.match(backgroundPattern);
			var matchBackgroundSimple = element.currentStyle.backgroundImage.match(backgroundPatternSimple);
			var matchImage = outer.match(imagePattern);

			if(matchBackgroundSimple) {
				if(matchBackground){
					element.style.backgroundImage = '';
				} else {
					Style.remove('backgroundImage', '#'+element.id);
				}

				element.addAlphaImageLoader(matchBackgroundSimple[2]);
			}
			
			if(matchImage) {
				var imgWidth = element.width;
				var imgHeight = element.height;
				
				element.src = Util.Image.noImagem;
				element.addAlphaImageLoader(matchImage[3]);
				element.style.width = imgWidth;
				element.style.height = imgHeight;
			}

			element.removeClassName("png");
		}
	}	
});

Images.Methods = {
	over: function(element) {
		if (!element.onmouseout) {
			element.onmouseout = function() { $(this).over(); };
		}

		if (!element.style.cursor) {
			element.style.cursor = 'pointer';
		}

		var sourceOfImage = element.getSourceOfImage();
		var setImage = undefined;

		var srcImage = element.src;
		var srcOverImage = sourceOfImage.nameOfImage + Util.Image.over + "." + sourceOfImage.typeOfImage;
		var srcOriginalImage = sourceOfImage.nameOfImage + "." + sourceOfImage.typeOfImage;

		Images.preLoad(srcOverImage);

		if (element.src == srcOverImage || element.getNameOfImageByFilter() == srcOverImage) {
			setImage = srcOriginalImage;
		} else {
			setImage = srcOverImage;
		}

		if (sourceOfImage.typeOfImage.toLowerCase() == 'png' && Util.Browser.IE) {
			element.addAlphaImageLoader(setImage);
		} else {
			element.src = setImage;
		}

		return element;
	},

	getSourceOfImage: function(element) {
		var sourceOfImage = {nameOfImage: undefined, typeOfImage: undefined};
		var source = element.src;

		if (Util.Browser.IE && source == Util.Image.noImagem) {
			source = element.getNameOfImageByFilter();
		}

		var len = source.length;
		var size = 4;
		if (source.search(Util.Image.over + ".") > -1) { size = Util.Image.over.length + size; }

		sourceOfImage.nameOfImage = source.substr(0, len - size);
		sourceOfImage.typeOfImage = source.substr(len - 3, len);

		return sourceOfImage;
	},

	getTypeOfImage: function(element) {
		return element.getSourceOfImage().typeOfImage;
	},
	
	getNameOfImage: function(element) {
		return element.getSourceOfImage().nameOfImage;
	},
	
	getNameOfImageByFilter: function(element) {
		if (!Util.Browser.IE) { return undefined; }

		var outer = element.outerHTML;
		
		var backgroundPattern = /src=\s*([\"\']?)([^\)]+\.png)\1/i;
		var matchBackground = outer.match(backgroundPattern);

		return matchBackground ? matchBackground[2] : null;
	}
};

Element.addMethods();
Element.addMethods("img", Images.Methods);

if (Util.Browser.IE ) {
	if (parseFloat(navigator.appVersion.split("MSIE")[1]) < 7) {
		Style.create({'.png': 'visibility: hidden'});
		window.attachEvent('onload',Images.fixPngForIe);
	}
}