Array.each(['log', 'info', 'warn', 'error'], function(n) { window[n] = (typeof(console) == 'undefined' || typeof(console[n]) == 'undefined') ? function() { } : console[n]; });
window.test = window.log;


document.forward = function(loc) {
	if(!loc.match(/^([a-z]+:\/\/|\/)/i)) {
		var basehref = '';

		var lst = $(document).getElements('base');
		for(var i=0; i<lst.length; ++i) {
			if(lst[i].getAttribute('href')) {
				basehref = lst[i].getAttribute('href').trim();
				break;
			}
		}
		if(!basehref) basehref = '/';
		if(!basehref.match(/\/$/)) basehref += '/';
		loc = basehref + loc;
	}
	document.location = loc;
}
window.redirect = document.forward;


/********************************************************************/
// validate_email()
// returns true if email appears valid
/********************************************************************/
function validate_email(email) {
	email = email.trim();
	if( email.match(/(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/) || !email.match(/^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/) ) return false;
	return true;
}


/* toHash() method for forms */
Element.implement({
	'toHash': function() {

		if(this.tagName == 'FORM') {
			var data = { };


			this.getElements('input, select, textarea').each(function(el) {
				if (!el.name || el.disabled || el.type == 'submit' || el.type == 'reset' || el.type == 'file' || el.type == 'button' ) return;
				var value = (el.tagName.toLowerCase() == 'select') ? Element.getSelected(el).map( function(opt) { return opt.value; }) : ((el.type == 'radio' || el.type == 'checkbox') && !el.checked) ? null : el.value;

				$splat(value).each(function(val) {
					if (typeof val != 'undefined') {
						data[el.name] = val;
					}
				});
			});
			return data;
		}
		else return false;
	}
});




Overlay = new Class({
	Implements: [Options, Events],
	options: {
		className: 'overlay',
		styles: {
			background:	'#000000',
			opacity:	'0.5',
			zIndex:		95
		},
		tween: {
			show: { duration: 1000 },
			hide: { duration: 1000 }
		},
		onClick: function() { this.hide() }
	},

	locked:	true,
	status:	'locked',
	element: null,

	initialize: function(options) {
		this.setStatus('initializing').fireEvent('initialize');
		this.setOptions(options);

		this.element = new Element('div', { 'styles': this.options.styles, 'class': this.options.className })
		.setStyles({ position: 'absolute', display: 'none', top: 0, left: 0 })
		.addEvent('click', function() { this.fireEvent('click') }.bind(this))
		.inject($(document.body));

		window.addEvent('resize', this.resize.bind(this));
		this.setStatus('hidden');
	},

	show: function() {
		if(this.locked || this.status != 'hidden') return;
		this.setStatus('transitioning').fireEvent('show');

		this.resize();
		this.element.setStyles({ display: 'block', opacity: 0});

		var tween = new Fx.Tween(this.element, this.options.tween.show || this.options.tween);
		tween.addEvents({
			start: function() { this.fireEvent('start') }.bind(this),
			complete: function() { this.fireEvent('stop').setStatus('visible') }.bind(this)
		});
		tween.start('opacity', this.options.styles.opacity);
	},

	hide: function() {
		if(this.locked || this.status != 'visible') return;
		this.setStatus('transitioning').fireEvent('hide');

		var tween = new Fx.Tween(this.element, this.options.tween.hide || this.options.tween);
		tween.addEvents({
			start: function() { this.fireEvent('start') }.bind(this),
			complete: function() {
				this.element.setStyle('display', 'none');
				this.fireEvent('stop').setStatus('hidden');
			}.bind(this)
		});
		tween.start('opacity', 0);
	},

	setStatus: function(status) {
		var old = { status: this.status, locked: this.locked };

		switch(status) {
			case 'initializing':
			case 'locked':
			case 'transitioning':
				this.locked = true;
				this.status = status;
				break;

			case 'visible':
			case 'hidden':
				this.locked = false;
				this.status = status;
				break;

			default:
				this.locked = true;
				this.status = 'void';
		}
		if(this.status != old.status) this.fireEvent('statusChange', { old_status: old.status, new_status: this.status });
		if(this.locked != old.locked) this.fireEvent( this.locked ? 'lock' : 'unlock' );

		return this;
	},

	resize: function() {
		var db = $(document.body);
		this.element.setStyles({
			top: 0, left: 0,
			width: db.getScrollWidth(),
			height: db.getScrollHeight() 
		});

		this.fireEvent('resize');
		return this;
	}
});




DisplayDivNewNotFinished = new Class({
	Implements: [Options, Events],

	options: {
		tween: {
			show: { duration: 1000 },
			hide: { duration: 1000 }
		},

		onStart: function() { test('onStart') },
		onStop: function() { test('onStop') },
		onShow: function() { test('onShow') },
		onHide: function() { test('onHide') },
		onLock: function() { test('onLock') },
		onUnlock: function() { test('onUnlock') },
		onStatusChange: function(e) { test('onStatusChange: ' + e.old_status + ' -> ' + e.new_status) },
		onInit:		function(e) { test('onInit') },
		onResize:	function(e) { test('onResize') }
	},

	locked:	true,
	status:	'locked',
	element: null,

	initialize: function(element, options) {
		this.setStatus('initializing').fireEvent('initialize');
		this.setOptions(options);

		this.element = $(element).setStyles({ position:'absolute', zIndex:1001, top: 0, left:0 });
		this.overlay = new Overlay();

		window.addEvent('resize', this.resize.bind(this));
		this.setStatus('hidden');
	},

	show: function() {
		if(this.locked || this.status != 'hidden') return;
		this.setStatus('transitioning').fireEvent('show');

		this.element.setStyles({ display: 'block', opacity: 0});
		this.resize();

		var tween = new Fx.Tween(this.element, this.options.tween.show || this.options.tween);
		tween.addEvents({
			start: function() { this.fireEvent('start') }.bind(this),
			complete: function() { this.fireEvent('stop').setStatus('visible') }.bind(this)
		});
		tween.start('opacity', this.options.styles.opacity);
	},

	hide: function() {
		if(this.locked || this.status != 'visible') return;
		this.setStatus('transitioning').fireEvent('hide');

		var tween = new Fx.Tween(this.element, this.options.tween.hide || this.options.tween);
		tween.addEvents({
			start: function() { this.fireEvent('start') }.bind(this),
			complete: function() {
				this.element.setStyle('display', 'none');
				this.fireEvent('stop').setStatus('hidden');
			}.bind(this)
		});
		tween.start('opacity', 0);
	},

	setStatus: function(status) {
		var old = { status: this.status, locked: this.locked };

		switch(status) {
			case 'initializing':
			case 'locked':
			case 'transitioning':
				this.locked = true;
				this.status = status;
				break;

			case 'visible':
			case 'hidden':
				this.locked = false;
				this.status = status;
				break;

			default:
				this.locked = true;
				this.status = 'void';
		}
		if(this.status != old.status) this.fireEvent('statusChange', { old_status: old.status, new_status: this.status });
		if(this.locked != old.locked) this.fireEvent( this.locked ? 'lock' : 'unlock' );

		return this;
	},

	resize: function() {
		var db = $(document.body);

		this.element.setStyles({
			display: 'block',
			top: 0, left: 0,
			opacity: (this.status == 'visible') ? 1 : 0
		 }).setStyles({
			top: (db.getHeight() / 2), // - (this.element.getHeight() / 2)+ db.getScroll().y,
			left: (db.getWidth() / 2) - (this.element.getWidth() / 2),
			opacity: 1			
		});

		this.fireEvent('resize');
		return this;
	}
});

DisplayDiv = new Class({
	Implements: Options,

	options: {
		duration:		1000,
		transition:		Fx.Transitions.Cubic.easeOut,
		overlay:		true,
		transition_types:	['morph', 'fade'] // morph, fade
	},

	initialize: function(element, options){
		this.element = $(element);
		this.setOptions(options);
		this._inTransition = false;
		this._curWay = 0;
		this._fx = null;
		this.id = this.__register();

		var self = this;
		var id = this.id;

		this.elOpacity = (this.element.style.opacity) ? this.element.style.opacity : this.element.getStyle('opacity') ;

		this.element.setStyle('overflow', 'hidden');

		this.set_dimensions();

		this.element.setStyle('width', this.elWidth); // fixed width

		window.addEvent('resize', function() { this.__registerDisplayDivClasses[id].setPosition(); });
		window.addEvent('scroll', function() { this.__registerDisplayDivClasses[id].setPosition(); });

		if(this.options.overlay) {
			this.options.overlay.onClick = function() { self.hide(true); }
			this.overlay = new Overlay(this.options.overlay);
			this.options.overlay = true;
		}


		this.reset();
	},


	__register: function() {
		if(!window.__registerDisplayDivClasses) window.__registerDisplayDivClasses = new Array();
		window.__registerDisplayDivClasses.push(this);
		return window.__registerDisplayDivClasses.length - 1;
	},

	set_dimensions: function() {
		if(this.element.getStyle('display') == 'none') {

			var vis = this.element.getStyle('visibility');
			var dis = this.element.getStyle('display');
			this.element.setStyle('visibility', 'hidden');
			this.element.setStyle('display', 'block');

			this.elWidth = this.element.getWidth();
			this.elHeight = this.element.scrollHeight;

			this.element.setStyle('display', dis);
			this.element.setStyle('visibility', vis);
		} else {
			this.elWidth = this.element.getWidth();
			this.elHeight = this.element.scrollHeight;
		}
	},

	reset: function() {
		this.element.setStyle('overflow', 'hidden');
		this._inTransition = false;
		this._curWay = 0;

		this.setPosition();


		for(var t=0; t<this.options.transition_types.length; ++t) {
			switch(this.options.transition_types[t]) {
				case 'morph':
					this.element.setStyle('height', '1px');
					break;
	
				case 'fade':
					this.element.setStyle('opacity', 0.0);
					break;
			}
		}

	},

	setPosition: function() {

		var style = new Object;
		var dbody = $(document.body);
		style.left = ( (dbody.getWidth() / 2) - (this.elWidth / 2) + dbody.getScroll().x );
		style.top = ( (dbody.getHeight() / 2) - (this.elHeight / 2) + dbody.getScroll().y );


		this.element.setStyles(style);

		this.elTop = this.element.getTop();
		this.elLeft = this.element.getLeft();


	},

	toggle: function() {
		(this._curWay == 1) ? this.hide() : this.show();
	},

	show: function() {
		if(this._inTransition) this._fx.cancel();
		else this.set_dimensions();

		var self = this;

		var to = new Object;

		for(var t=0; t<this.options.transition_types.length; ++t) {
			switch(this.options.transition_types[t]) {
				case 'morph':
					to.height = this.elHeight;
					break;
	
				case 'fade':
					to.opacity = this.elOpacity;
					break;
			}
		}


		if(this.options.overlay) this.overlay.show();

		this._fx = new Fx.Morph( this.element, {
			duration: self.options.duration,
			transition: self.options.transition,
			onStart: function() {
				self._inTransition = true;
				self._curWay = 1;
				this.element.style.display = 'block';
			},
			onComplete: function() {
				self._inTransition = false;
			}
		});

		this._fx.start(to);
	},

	hide: function() {
		if(this._inTransition) this._fx.cancel();

		var self = this;

		var to = new Object;
		for(var t=0; t<this.options.transition_types.length; ++t) {
			switch(this.options.transition_types[t]) {
				case 'morph':
					to.height = 1;
					break;
	
				case 'fade':
					to.opacity = 0;
					break;
			}
		}

		if(this.options.overlay) this.overlay.hide();

		this._fx = new Fx.Morph( this.element, {
			duration: self.options.duration,
			transition: self.options.transition,
			onStart: function() {
				self._inTransition = true;
				self._curWay = 0;
			},
			onComplete: function() {
				self._inTransition = false;
				this.element.style.display = 'none';
			}
		});

		this._fx.start(to);
	}

});






/********************************************************************/
splat		= function(v) { return Array.from(v); };
intval		= function(v, base) { switch(typeof(v)) { case 'boolean': return +v; case 'string': var tmp = parseInt(v, base || 10); return (isNaN(tmp) || !isFinite(tmp)) ? 0 : tmp; case 'number': if(isFinite(v)) return v | 0; default: return 0; } };
floatval	= function(v) { return (parseFloat(v) || 0); }
uid		= function() { return String.uniqueID() };











