var TringMeSidebar = new Class({
	Implements: [Options, Events],

	options: {
		height: 220,
		width: 150,
		slideDuration: 1000,
		opacityDuration: 1500,
		contentDivClass: 'sideBarContents',
		clickHandleClass: 'showop',
		clickHandleFunc: null
	},

	initialize: function(element, options){
		this.setOptions(options);
		this.isExtended = 0;
		this.element = $(element);
		this.element.addEvent('click', this.extendContract.bind(this));
		this.addEvent('resizeComplete', this.chromeHandler.bind(this));
		$(this.options.contentDivClass).addClass('hide');
		if(null!=this.options.clickHandleFunc)
			$$('a.' + this.options.clickHandleClass).each((function(el){ el.addEvent('click', this.options.clickHandleFunc); }).bind(this));
		document.addEvent('click', this.clickedOutside.bind(this));
	},

	extendContract: function(evt){
		if(null!=evt)
			evt.stop();
		if(this.isExtended == 0){
			this.sideBarSlide(0, this.options.height, 0, this.options.width);
			this.sideBarOpacity(0, 1);
			this.isExtended = 1;
			$(this.options.contentDivClass).removeClass('hide');
			// make expand tab arrow image face left (inwards)
			this.element.getChildren()[0].src = this.element.getChildren()[0].src.replace(/(\.[^.]+)$/, '-active$1');
		} else {
			this.sideBarSlide(this.options.height, 0, this.options.width, 0);
			this.sideBarOpacity(1, 0);
			this.isExtended = 0;
			// make expand tab arrow image face right (outwards)
			this.element.getChildren()[0].src =this.element.getChildren()[0].src.replace(/-active(\.[^.]+)$/, '$1');
		}
	},

	sideBarSlide: function(fromHeight, toHeight, fromWidth, toWidth){
		var myEffects = new Fx.Morph(this.options.contentDivClass, {duration: this.options.slideDuration, transition: Fx.Transitions.linear});
		myEffects.addEvent('complete', (function(){ this.fireEvent('resizeComplete', this); }).bind(this) );
		myEffects.start({
			'height': [fromHeight, toHeight],
			'width': [fromWidth, toWidth]
		});
	},

	sideBarOpacity: function(from, to){
		var myEffects = new Fx.Morph(this.options.contentDivClass, {duration: this.options.opacityDuration, transition: Fx.Transitions.linear});
		myEffects.addEvent('complete', (function(){ this.fireEvent('opacityComplete', this); }).bind(this) );
		myEffects.start({
			'opacity': [from, to]
		});
	},

	chromeHandler: function(obj) {
		if(this.isExtended == 0)
			$(this.options.contentDivClass).addClass('hide');
	},

	clickedOutside: function(evt) {
		if(0==this.isExtended)
			return;
		if(evt.rightClick)
			return;
		var elInfo = $(this.options.contentDivClass).getCoordinates();
		var ignoreX = false, ignoreY = false;
		if(elInfo.left < evt.page.x && evt.page.x < elInfo.right)
			ignoreX = true;
		if(elInfo.top < evt.page.y && evt.page.y < elInfo.bottom)
			ignoreY = true;
		if(ignoreX && ignoreY)
			return;
		(this.extendContract.bind(this))();
	}
});

var TringMeWindowFx = new Class({
	Implements: [Options, Events],

	options: {
		startFxId: 'sideBar',
		fxDuration: 250,
		dragContainer: 'main',
		dragDroppables: 'content'
	},

	initialize: function(element, options){
		if(null == $(element))
			return null;

		this.setOptions(options);
		this.element = $(element);

		this.isShown = false;
		this.isShowingInProgress = false;
		if(null==this.options.closeElem) {
			this.options.closeElem = this.element.getElement('.close');
		}
		if(null!=this.options.closeElem) {
			this.options.closeElem = $(this.options.closeElem);
			this.options.closeElem.addEvent('click', this.closeWindow.bind(this));
		}
		if(null==this.options.dragElem) {
			this.options.dragElem = this.element.getElement('.topbar');
		}
		if(null!=this.options.dragElem) {
			this.options.dragElem = $(this.options.dragElem);
		}
		this.dragFx = new Drag.Move(this.element, {
			handle: (null==this.options.dragElem?this.element:this.options.dragElem),
			container: $(this.options.dragContainer),
			droppables: $(this.options.dragDroppables),
			onDrop: this.cookieSavePos.bind(this)
		});
	},

	showWindow: function() {
		if(this.isShowingInProgress)
			return;
		
		if(this.isShown)
			return;
		
		this.isShowingInProgress = true;
		var id = this.element.get('id');
		var posId = id.replace("_","-").camelCase();
		var startFxElem = $(this.options.startFxId);
		var initialPos = new Object();
		initialPos.top = 0;
		initialPos.left = 0;
		if(null!=startFxElem) {
			initialPos = startFxElem.getCoordinates();
		}

		var styles = this.element.getProperty('style');
		if(null==styles)
			styles = this.element.style.cssText;
		this.element.store('defStyles', styles);
		this.element.setStyle('opacity', 0);
		this.element.removeClass('hide');
		if('none'==this.element.getStyle('display'))
			this.element.setStyle('display', 'block');
		var elemPos = this.element.getCoordinates();

		var res = Cookie.read('position');
		var savedpos = JSON.decode(res);
		if(null==savedpos)
			savedpos = new Object();
		if(null==savedpos[posId]) {
			savedpos[posId] = new Object();
			var body = this.element.getParent().getCoordinates();
			savedpos[posId].x = parseInt(body.width - elemPos.width - 20);
			savedpos[posId].y = parseInt((body.height - elemPos.height)/2);
		}

		var moveResizePos = new Fx.Morph(this.element, {duration: this.options.fxDuration, transition: Fx.Transitions.linear});
		moveResizePos.addEvent('complete', (function(){
			this.element.setStyle('height', 'auto');
			this.isShown = true;
			this.isShowingInProgress = false;
			this.fireEvent('showWindowComplete', this.element);
		}).bind(this));

		moveResizePos.start({
			'width': [20, elemPos.width],
			'height': [20, elemPos.height],
			'opacity': [0, 1],
			'top': [initialPos.top, savedpos[posId].y],
			'left': [initialPos.left, savedpos[posId].x]
		});		
	},

	closeWindow: function() {
		if(false==this.isShown)
			return;
		this.fireEvent('closeWindowStart', this.element);
		var id = this.element.get('id');
		var posId = id.replace("_","-").camelCase();
		var endFxElem = $(this.options.startFxId);
		var endPos = new Object();
		endPos.top = 0;
		endPos.left = 0;
		if(null!=endFxElem) {
			endPos = endFxElem.getCoordinates();
		}
		var elemPos = this.element.getCoordinates();
		//var styles = this.element.getProperty('style');
		//this.element.store('defStyles', styles);
		//tringmelog(endPos);
		//tringmelog(elemPos);

		var res = Cookie.read('position');
		var savedpos = JSON.decode(res);
		if(null==savedpos)
			savedpos = new Object();
		if(null==savedpos[posId]) {
			savedpos[posId] = new Object();
			var body = this.element.getParent().getCoordinates();
			savedpos[posId].x = parseInt(body.width - elemPos.width - 20);
			savedpos[posId].y = parseInt((body.height - elemPos.height)/2);
		}

		var moveResizePos = new Fx.Morph(this.element, {duration: this.options.fxDuration, transition: Fx.Transitions.linear});
		moveResizePos.addEvent('complete', (function(){
			this.element.removeProperty('style');
			if(null!=this.element.retrieve('defStyles')) {
				this.element.setProperty('style', this.element.retrieve('defStyles'));
				if(this.element.style.cssText != this.element.retrieve('defStyles'))
					this.element.style.cssText = this.element.retrieve('defStyles');
			}
			this.element.eliminate('defStyles');
			this.element.addClass('hide');
			if('block'==this.element.getStyle('display'))
				this.element.setStyle('display', 'none');
			this.isShown = false;
			this.isShowingInProgress = false;
			this.fireEvent('closeWindowComplete', this.element);
		}).bind(this));

		moveResizePos.start({
			'width': [elemPos.width, 20],
			'height': [elemPos.height, 20],
			'opacity': [1, 0],
			'top': [savedpos[posId].y, endPos.top],
			'left': [savedpos[posId].x, endPos.left]
		});
	},

	cookieSavePos: function(el, drop) {
		var pos = el.getPosition(el.getParent());
		var id = el.get('id').replace("_","-").camelCase();
		var res = Cookie.read('position');
		var savedpos = JSON.decode(res);
		if(null==savedpos)
			savedpos = new Object();
		savedpos[id] = pos;
		res = JSON.encode(savedpos);
		Cookie.write('position', res);
		this.fireEvent('dragComplete', [el, drop]);
	},

	isVisible: function() {
		return this.isShown;
	},

	isAnimation: function() {
		return this.isShowingInProgress;
	}
});

var TringMePopupMessage = new Class({
	Implements: [Options, Events],

	options: {
		width: 250,
		fxDuration: 500,
		clickHandleFunc: null,
		showSpinner: false,
		timeout: 5000,
		defaultTimeout: 15000,
		defaultWidth: 250
	},

	initialize: function(message, options){
		this.setOptions(options);
		this.timedMessageClear = -1;
		this.isMessageDisplaying = false;
		this.isMessageDisplayed = false;
		this.createPopupMessage(message);
		this.bgFx = null;
		this.contentFx = null;
	},

	showMessage: function(message, showspinner, timeout, width){
		if(this.isMessageDisplayed || this.isMessageDisplaying) {
			if(this.timedMessageClear > 0)
				clearTimeout(this.timedMessageClear);
			if(this.isMessageDisplaying && !this.isMessageDisplayed)
				this.removePopupMessage.delay(250, this, [message, showspinner, timeout, width]);
			else
			this.removePopupMessage.pass([message, showspinner, timeout, width], this)();
			return;
		}
		this.timedMessageClear = -1;
		this.options.timeout = timeout;
		this.options.width = width;
		this.options.showSpinner = (true===showspinner);
		this.isMessageDisplaying = false;
		this.isMessageDisplayed = false;
		this.createPopupMessage(message);
	},

	createPopupMessage: function(message) {
		if(null==message)
			return;
		//tringmelog(message);
		var mnh = $('messagenotificationholder');
		if(null==mnh) {
			mnh = new Element('div', {'id': "messagenotificationholder", styles: {zIndex: -1, opacity: 0}});
			mnh.inject(document.body);
		} else
			mnh.setStyles({zIndex: -1, opacity: 0});
		mnh.empty();
		this.contentDiv = new Element('div', {'class': "messagenotificationcontent"});
		if(this.options.showSpinner)
			(new Element('img', {src: "images/spinner.gif", styles: {marginRight: 10}})).inject(this.contentDiv);
		if(instanceOf(message, String) || 'string'==typeOf(message)) {
			message = message.replace('\n', '<br />');
			var testForBR = new RegExp('<br />', 'gi');
			var h = message.match(testForBR);
			if(null!=h) {
				var fntSize = this.contentDiv.getStyle('font-size');
				fntSize = (null==fntSize)?12:fntSize;
				h = h.length * parseInt(fntSize);
				var divH = parseInt(this.contentDiv.getStyle('height'));
				if(divH<=fntSize)
					divH = fntSize * 2;
				this.contentDiv.setStyle('height', divH + h + 'px');
				$('notification').setStyle('height', parseInt($('notification').getStyle('height')) + h + 'px');
			}
			this.contentDiv.set('html', this.contentDiv.get('html') + message);
		} else {
			message.inject(this.contentDiv);
			var h = message.offsetHeight;
			var w = message.offsetWidth;
			if(null!=h && h>0) {
				var divH = parseInt(this.contentDiv.getStyle('height'));
				var fntSize = this.contentDiv.getStyle('font-size');
				fntSize = (null==fntSize)?12:fntSize;
				if(divH<=fntSize)
					divH = fntSize * 2;
				this.contentDiv.setStyle('height', divH + h + 'px');
				$('notification').setStyle('height', parseInt($('notification').getStyle('height')) + h + 'px');
			}
			if(this.options.width < w) {
				this.options.width = w;
				this.contentDiv.setStyle('width', w + 'px');
			}
		}

		this.bgDiv = new Element('div', {'class': "messagenotificationbg"});
		this.bgDiv.inject(mnh);
		this.contentDiv.inject(mnh);
		var divInfo = this.contentDiv.getCoordinates();
		var divStyles = {top: (parseInt(-divInfo.height * 1.5) - 20), left: parseInt(-divInfo.width * 0.5)};
		var bgStyles = {top: (parseInt(-divInfo.height/2) - 10), left: (parseInt(-divInfo.width/2) -10), height: (divInfo.height + 20), width: (divInfo.width + 20)};
		this.contentDiv.setStyles(divStyles);
		this.bgDiv.setStyles(bgStyles);
		this.showPopupMessage();
	},

	showPopupMessage: function() {
		var divInfo = this.contentDiv.getCoordinates();
		var contentVisibilityFx = new Fx.Morph(this.contentDiv, {duration: this.options.fxDuration, transition: Fx.Transitions.linear});
		var bgVisibilityFx = new Fx.Morph(this.bgDiv, {duration: this.options.fxDuration, transition: Fx.Transitions.linear});

		contentVisibilityFx.addEvent('complete', this.autoRemove.bind(this));

		this.bgFx = bgVisibilityFx;
		this.contentFx = contentVisibilityFx;

		if(divInfo.width < this.options.width)
			divInfo.width = this.options.width;

		contentVisibilityFx.start({
			'width': [0, divInfo.width],
			'height': [0, divInfo.height],
			'opacity': [0, 1],
			'top': [0, (parseInt(-divInfo.height * 1.5) - 20)],
			'left': [0, parseInt(-divInfo.width * 0.5)]
		});
		bgVisibilityFx.start({
			'width': [0, (divInfo.width + 20)],
			'height': [0, (divInfo.height + 20)],
			'opacity': [0, 0.7],
			'top': [0, (parseInt(-divInfo.height * 0.5) - 10)],
			'left': [0, (parseInt(-divInfo.width * 0.5) -10)]
		});
		this.isMessageDisplaying = true;
		$('messagenotificationholder').setStyles({zIndex: 100, opacity: 1});
	},

	autoRemove: function() {
		this.isMessageDisplayed = true;

		this.options.timeout = null==this.options.timeout?this.options.defaultTimeout:this.options.timeout;
		if(null!=this.options.timeout) {
			if(0==this.options.timeout)
				this.timedMessageClear = this.removePopupMessage.delay(this.options.defaultTimeout, this, [null, null, null]);
			else if(0<this.options.timeout)
				this.timedMessageClear = this.removePopupMessage.delay(this.options.timeout, this, [null, null, null]);
		}
	},

	removePopupMessage: function(message, showspinner, timeout, width) {
		if(null==this.contentDiv)
			return;
		if(false==this.isMessageDisplayed)
			return;
		if(null!=this.bgFx)
			this.bgFx.cancel();
		if(null!=this.contentFx)
			this.contentFx.cancel();

		if(this.isMessageDisplayed) {
		var divInfo = this.contentDiv.getCoordinates();
		var contentVisibilityFx = new Fx.Morph(this.contentDiv, {duration: this.options.fxDuration, transition: Fx.Transitions.linear});
		var bgVisibilityFx = new Fx.Morph(this.bgDiv, {duration: this.options.fxDuration, transition: Fx.Transitions.linear});

		contentVisibilityFx.addEvent('complete', this.destroyPopupMessage.pass([message, showspinner, timeout, width], this));

			this.bgFx = bgVisibilityFx;
			this.contentFx = contentVisibilityFx;

		contentVisibilityFx.start({
			'width': [divInfo.width, 0],
			'height': [divInfo.height, 0],
			'opacity': [1, 0],
			'top': [(parseInt(-divInfo.height * 1.5) - 20), 0],
			'left': [parseInt(-divInfo.width * 0.5), 0]
		});
		bgVisibilityFx.start({
			'width': [(divInfo.width + 20), 0],
			'height': [(divInfo.height + 20), 0],
			'opacity': [0.7, 0],
			'top': [(parseInt(-divInfo.height * 0.5) - 10), 0],
			'left': [(parseInt(-divInfo.width * 0.5) -10), 0]
		});
		this.isMessageDisplayed = false;
		} else {
			this.destroyPopupMessage.pass([message, showspinner, timeout, width], this)();
		}
	},

	destroyPopupMessage: function(message, showspinner, timeout, width) {
		this.bgFx = null;
		this.contentFx = null;
		if(null==$('messagenotificationholder')) {
			this.timedMessageClear = -1;
			return;
		}
		$('messagenotificationholder').empty();
		this.contentDiv = null;
		this.bgDiv = null;
		$('messagenotificationholder').setStyles({zIndex: -1, opacity: 0});
		this.isMessageDisplaying = false;
		this.options.width = (null!=width?width:this.options.defaultWidth);
		if(this.timedMessageClear > -1) {
			clearTimeout(this.timedMessageClear);
			this.timedMessageClear = -1;
		}
		if(null==message || undefined==message) 
			return;
		this.options.timeout = timeout;
		this.options.showSpinner = (true===showspinner);
		this.createPopupMessage(message);
	}
});
