/* WordsMixer 1.1 - 2011.05.11
/*
/* Created by Luca Pillonel
/* copyright www.oxima.ch
--------------------------------------*/

var WordsMixer = new Class({

	options : {
		translationDuration : 800,
		slowMotion : 4000,
		wordMinLength : 1,
		wrapper : 'wordsmixer',
		transition : 'quad:in:out',
		txtColor : '#434343',
		disabledTxtColor : '#ddd',
		wordspotOpacity : 0.1,
		wordspotSize : 14
	},
	
	initialize : function(){
		if(!$(this.options.wrapper)) return;
		
		this.opened = false;
		this.waitingFx = [];
		this.dictionary = new Hash();
		this.usedWords = new Hash();
		
		this.setElements();
		this.setOffsets();
		this.setDictionary();
	},
	
	setElements : function(){
		this.dictWrapper = new Element('div', {
			'id' : 'wordserlay-' + Math.floor(Math.random()*100000000),
			'class' : 'wordserlay'
		}).inject(this.options.wrapper, 'top');
	},
	
	setOffsets : function(){
		if(Browser.firefox || Browser.ie) {
			this.verticalOffset = 1;
		} else if(Browser.safari || Browser.chrome || Browser.opera) {
			this.verticalOffset = 2;
		} else {
			this.verticalOffset = 1;
		}
	},
	
	setDictionary : function(){
		//on chope tous les mots de plus de 4 caractères
		var uwords = new Array();
		
		$(this.options.wrapper).getElements('.service p').each(function(el){
			//prepare list
			var regexp = new RegExp('([a-z]{'+this.options.wordMinLength+',})', 'gi');
			var words = el.get('html').match(regexp);
			words.each(function(word){
				word = word.toLowerCase()
				if (!uwords.contains(word))
					uwords.push(word);
			});
			
			//add span to all words with more than 4 letters and hide paragraph
			el.set('html',el.get('html').replace(regexp, '<span>$1</span>')).setStyle('opacity', 0);
			
			this.setBehaviour(el);
		}, this);
		
		//add words to big list and generate hash
		var wordspot = $(this.options.wrapper).getElement('.wordspot').setStyle('opacity', this.options.wordspotOpacity);
		
		uwords.sort().each(function(word){
			var el = new Element('span', {
				html : word
			}).inject(wordspot);
			
			this.dictionary[word] = el;
			wordspot.appendText(' ');
		}, this);
	},
	
	animateWords : function(el, event){
		var duration = event.shift ? this.options.slowMotion : this.options.translationDuration;
		if(el != this.opened) {
			//get all span of the paragraph
			var constructingUsedWords = new Hash();
			el.getElements('span').each(function(word){
				var txt = word.get('text');
				
				//get it from dictionary or previous work
				if(this.usedWords[txt.toLowerCase()]) {
					var origin = this.usedWords[txt.toLowerCase()][0];
					var pos = origin.getPosition(this.dictWrapper);
					var initColor = this.options.txtColor;
					
					//remove it from usedWords
					this.usedWords[txt.toLowerCase()].shift();
					if(!this.usedWords[txt.toLowerCase()].length) {
						this.usedWords.erase(txt.toLowerCase());
					}
					
					origin.destroy();
				} else {
					var origin = this.dictionary[txt.toLowerCase()];
					origin.setStyle('visibility', 'hidden');
					var pos = origin.getPosition(this.dictWrapper);
					var initColor = this.options.disabledTxtColor;
				}
				
				var tpos = word.getPosition(this.dictWrapper);
				
				// create a new element and animate to new position
				var usedWord = new Element('span', {
					html : txt,
					styles : {
						position : 'absolute',
						left : pos.x,
						top : pos.y - this.verticalOffset,
						color : initColor,
						fontSize : this.options.wordspotSize
					}
				}).inject(this.dictWrapper).set('morph', {
					transition : this.options.transition,
					duration : duration
				}).morph({
					left : tpos.x,
					top : tpos.y - this.verticalOffset,
					color : this.options.txtColor,
					fontSize : 12
				});
				
				constructingUsedWords[txt.toLowerCase()] = constructingUsedWords[txt.toLowerCase()] || [];		
				constructingUsedWords[txt.toLowerCase()].push(usedWord);
			}, this);
		}
	
		this.revertRemainingUsedWords(el, duration);
		
		if(el != this.opened) {
			this.usedWords = constructingUsedWords;
			this.opened = el.set('tween', {
				transition : 'quad:in',
				duration : duration
			}).tween('opacity', 1);
		} else {
			this.opened = false;
			this.usedWords = false;
		}
	},
	
	revertRemainingUsedWords : function(el, duration){
		//revert all usedWords remaining
		if(this.opened) {
			var usedWords = this.usedWords.getValues().flatten();
			var length = usedWords.length;
			usedWords.each(function(word, i){
				//get his position in dictionnary
				var key = word.get('text').toLowerCase();
				var tar = this.dictionary[key];
				var pos = tar.getPosition(this.dictWrapper);
				var forcedVisibility = this.opened == el;
				
				word.set('morph', {
					duration : duration,
					transition : this.options.transition,
					onComplete : function(){
						word.destroy();
						if(!this.usedWords[key] || forcedVisibility )
							tar.setStyles({
								'visibility': 'visible'
							});
					}.bind(this)
				}).morph({
					left : pos.x,
					top : pos.y -1,
					color : this.options.disabledTxtColor,
					fontSize : this.options.wordspotSize
				});
			}, this);
			this.opened.set('tween', {
				transition : 'quad:out',
				duration : duration
			}).tween('opacity', 0);
		};
	},
	
	setBehaviour : function(el){
		el.getParent('.service').addEvents({
			'mouseenter' : function(e){
				e.preventDefault();
				if(this.opened != el)
					this.animateWords(el, e);
			}.bind(this),
			
			'click' : function(e){
				e.preventDefault();
				this.animateWords(el, e);
			}.bind(this)
		}, this);
		
		$(this.options.wrapper).getElement('.wordspot').addEvents({
			'mouseenter' : function(){
				$(this.options.wrapper).getElement('.wordspot').tween('opacity', 0.7);
			}.bind(this),
			
			'mouseleave' : function(){
				$(this.options.wrapper).getElement('.wordspot').tween('opacity', this.options.wordspotOpacity);
			}.bind(this)
		});
	}
});
