var PBB_MagicWheel = new Class({

	Implements: [Events, Options],

	options: {
		maxWidth: 0.9, // Largeur max du magicwheel en % de 0 à 1, en px > 1
		minWidth: 100, // Largeur min du magicwheel en % de 0 à 1, en px > 1
		maxHeight: 0.2, // Hauteur max du magicwheel en % de 0 à 1, en px > 1
		minHeight: 10, // Hauteur min du magicwheel en % de 0 à 1, en px > 1
		iconMaxWidth: 128, // Largeur des icons
		iconMinWidth : 0, // Largeur min des icons
		iconMinOpacity : 0, // Opacité min des icons
		gradReflection : 0.7, // Dégradé des réflections
		
		userIconWidth: 64,
		userIconMinWidth: 30,
		userWidth: null,
		userHeight: 5, // Facteur coeficiant de la hauteur
		userSpeed: 0.2, // Vitesse de base
		userIconOpacity: 1,
		userIconMinOpacity: 0.3, // Opacité min
		userRefOpacity: 0.7 // Opacité de la réfléction
	},

	initialize: function(el, options) {
		this.setOptions(options);
		
		this.magicwheel = el;
		this.screenSize = window.getSize();
		this.icons = this.magicwheel.getElements('.icon');
		
		this.counter = 1; // Conteur de la roue;
		this.speed = 0.2;
		this.iconover = false;
		this.tip = new Element('span', {'class': 'tip'}).inject(document.body);
		new Element('span').inject(this.tip);
		
		if(this.options.maxWidth <= 1) // converti en px si c'est en %
			this.options.maxWidth = this.screenSize.x * this.options.maxWidth;
		if(this.options.minWidth <= 1) // converti en px si c'est en %
			this.options.minWidth = this.screenSize.x * this.options.minWidth;
		if(this.options.maxHeight <= 1) // converti en px si c'est en %
			this.options.maxHeight = this.screenSize.y * this.options.maxHeight;
		if(this.options.minHeight <= 1) // converti en px si c'est en %
			this.options.minHeight = this.screenSize.y * this.options.minHeight;
		
		// Calcul la largeur en fonction de la taille des icons et du nombre d'icons
		var fx = this.icons.length * this.options.userIconWidth * 0.45;
		this.options.userWidth = (fx < this.options.maxWidth) ? fx : this.options.maxWidth; // initialise la taille par defaut
		
		// Check les settings
		this.checkSettings();
		
		this.magicwheel.addEvent('mousewheel', function(e){
			e.stop(); // prevent the mousewheel from scrolling the page.
			if(!this.iconover) {
				this.speed = e.wheel > 0 ? (this.speed-0.5) : (this.speed+0.5);
			}
			else {
				var move = 360 / this.icons.length / 57.3;
				this.counter = e.wheel > 0 ? (this.counter - move) : (this.counter + move);
				this.run(true);
			}
		}.bind(this));
		
		// Préparation au préchargement des images
		var PathImg = [];
		this.icons.each(function(el){
			if(el.get('src'))
				PathImg.include(el.get('src'));
		});
		
		// Préchargement des images
		new Asset.images(PathImg, {
			onProgress: function(i) {
				//console.log(i);
			}.bind(this),
			
			onComplete: function() {
				this.build();
			}.bind(this)
		});
	},
	
	build: function() {
		this.icons.each(function(el){
			var link = el.getParent().get('href');
			el.set('id', 'icon-'+link);
			this.addIconEvent(el);
			this.addIconReflection(el);
		}, this);
		
		this.magicwheel.removeClass('loading');
		
		this.run.periodical(50, this);
	},
	
	addIcon: function(link, icon, title) {
		//if($('icon-'+link))
		//	return;
		
		this.magicwheel.addClass('loading');
		
		var newA = new Element('a', {
			'title': title,
			'href': link
		});
		
		var newIcon = new Element('img', {
			'id': 'icon-'+link,
			'class': 'icon',
			'src': icon
		}).inject(newA.inject(this.magicwheel));
		
		new Asset.image(icon, {
			onload: function() {
				this.addIconEvent(newIcon);
				this.icons = this.magicwheel.getElements('.icon');
				this.addIconReflection(newIcon);
				this.magicwheel.removeClass('loading');
			}.bind(this, newIcon)
		});
	},
	
	addIconEvent: function(icon) {
		var title = icon.retrieve('tip:title', icon.getParent().get('title'));
		if(!title)
			title = icon.retrieve('tip:title', icon.getParent().get('href'));
		icon.getParent().erase('title');
		
		icon.addEvent('mouseover', function(icon){
			this.iconover = true;
			this.tip.getFirst().set('text', icon.retrieve('tip:title'));
			
			var icon_size = icon.getCoordinates();
			var tip_size = this.tip.getSize();
			
			this.tip.setStyles({
				left: icon_size.left - tip_size.x / 2 + icon_size.width / 2,
				top: icon_size.top - tip_size.y - 2,
				opacity: 0.7
			});
		}.bind(this, icon)).addEvent('mouseout', function(el){
			this.tip.setStyle('visibility','hidden');
			this.iconover = false;
		}.bind(this));
	},
	
	addIconReflection: function(icon) {
		// Ajoute la réflections des icons
		if(this.options.gradReflection > 0) {
			if(Browser.Engine.trident) { // Pour les navigateur ne suportant pas canvas
				var ref = icon.clone();
				new Element('div').setStyles({'width':ref.width, 'height':ref.height}).addClass('ref').adopt(ref).inject(this.magicwheel);
				ref.setStyles({
					'filter': 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity='+(this.options.gradReflection*100)+', style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy='+(this.options.gradReflection*100)+')',
					'width':'100%',
					'height':'100%'
				});
			}
			else {
				var size = icon.getSize();
				var reflection = new Element('canvas', {'styles': {'width': size.x, 'height': size.y}});
				if (reflection.getContext) {
					var context = reflection.setProperties({'width': size.x, 'height': size.y}).getContext('2d');
					context.save();
					context.translate(0, size.y-1);
					context.scale(1, -1);
					context.drawImage(icon, 0, 0, size.x, size.y);
					context.restore();
					context.globalCompositeOperation = 'destination-out';
					var gradient = context.createLinearGradient(0, 0, 0, size.y);
					gradient.addColorStop(0, 'rgba(255, 255, 255, '+(1-this.options.gradReflection)+')');
					gradient.addColorStop(1, 'rgba(255, 255, 255, 1.0)');
					context.fillStyle = gradient;
					context.rect(0, 0, size.x, size.y);
					context.fill();
				}
				reflection.addClass('ref').inject(this.magicwheel);
			}
			this.reflections = this.magicwheel.getElements('.ref');
		}
	},
	
	checkSettings: function() {
		// Largeur des icons
		if(this.options.userIconWidth > this.options.iconMaxWidth)
			this.options.userIconWidth = this.options.iconMaxWidth;
		if(this.options.userIconWidth < this.options.iconMinWidth)
			this.options.userIconWidth = this.options.iconMinWidth;
		// Largeur minimal des icons
		if(this.options.userIconMinWidth > this.options.userIconWidth)
			this.options.userIconMinWidth = this.options.userIconWidth;
		if(this.options.userIconMinWidth < this.options.iconMinWidth)
			this.options.userIconMinWidth = this.options.iconMinWidth;
		// Largeur du magicwheel
		if(this.options.userWidth > this.options.maxWidth - this.options.userIconWidth)
			this.options.userWidth = this.options.maxWidth - this.options.userIconWidth;
		if(this.options.userWidth < this.options.minWidth)
			this.options.userWidth = this.options.minWidth;
		// Hauteur du magicwheel
		if(this.options.userHeight * this.icons.length > this.options.maxHeight)
			this.options.userHeight = this.options.maxHeight / this.icons.length;
		if(this.options.userHeight * this.icons.length < this.options.minHeight)
			this.options.userHeight = this.options.minHeight / this.icons.length;
		// Vitesse du magicwheel
		if(this.options.userSpeed > 1)
			this.options.userSpeed = 1;
		if(this.options.userSpeed < -1)
			this.options.userSpeed = -1;
		// Opacité des icons
		if(this.options.userIconOpacity > 1)
			this.options.userIconOpacity = 1;
		if(this.options.userIconOpacity < this.options.iconMinOpacity)
			this.options.userIconOpacity = this.options.iconMinOpacity;
		// Opacité minimal des icons
		if(this.options.userIconMinOpacity > this.options.userIconOpacity)
			this.options.userIconMinOpacity = this.options.userIconOpacity;
		if(this.options.userIconMinOpacity < this.options.iconMinOpacity)
			this.options.userIconMinOpacity = this.options.iconMinOpacity;
		// Opacité des réflections
		if(this.options.userRefOpacity > 1)
			this.options.userRefOpacity = 1;
		if(this.options.userRefOpacity < 0)
			this.options.userRefOpacity = 0;
		
		this.cX = this.screenSize.x / 2; // position central X du magicwheel
		this.cY = this.screenSize.y / 2; // position central Y du magicwheel
		
		this.dX = this.options.userWidth;
		this.rX = this.dX / 2; // largeur du rayon X du magicwheel
		
		this.dY = this.options.userHeight * this.icons.length ;
		this.rY = this.dY / 2;  // hauteur du rayon Y du magicwheel
		
		this.magicwheel.setStyles({
			top: this.cY - this.rY,
			left: this.cX - this.rX - this.options.userIconWidth / 2,
			width: this.dX  + this.options.userIconWidth,
			height: this.dY + this.options.userIconWidth
		});
	},
	
	run: function(f) {
		 if(this.iconover && !f)
			return;
		
		this.tip.setStyle('visibility','hidden');
		
		// Speed Max et Min du magicwheel
		if(!this.iconover) {
			if(this.speed > 3)
				this.speed = 3;
			else if(this.speed < -3)
				this.speed = -3;
		}
		
		for(i=0; i <= this.icons.length; i++){
			if(this.icons[i]) { // I do this to remove amazing last icon relfection bug !!!!
				var favA = i * ( Math.PI * 2 ) / this.icons.length; // Angle
				var favX = ( Math.sin( this.counter + favA )* this.rX); // Position X
				var favY = ( Math.cos( this.counter + favA )* this.rY); // Position Y
				var favP = (favY + this.rY) / this.dY; // position en % de l'image (0 = au fond, 1 = devant)
				var favW = this.options.userIconWidth * favP; // largeur final de l'image
				if(favW < this.options.userIconMinWidth)
					favW = this.options.userIconMinWidth;
				var favO = this.options.userIconOpacity * favP; // Opacité de l'image
				if(favO < this.options.userIconMinOpacity)
					favO = this.options.userIconMinOpacity;
				
				this.icons[i].setStyles({
					left: favX + this.rX + this.options.userIconWidth/2 - favW / 2,
					top: favY + this.rY - Math.abs(this.speed * 5),
					width: favW,
					zIndex: (100 * favP),
					opacity: favO
				});
				
				if(this.reflections[i]) {
					var icon = this.icons[i].getSize();
					
					this.reflections[i].setStyles({
						left: favX + this.rX + this.options.userIconWidth/2 - favW / 2,
						top: favY + this.rY + icon.y + Math.abs(this.speed * 5),
						width: favW,
						height: icon.y,
						zIndex: (100 * favP),
						opacity: favO*this.options.userRefOpacity - Math.abs(this.speed) * 0.3 + 0.1
					});
				}
			}
			else
				var icon = this.icons[i-1].getSize(); // I do this to remove amazing last icon relfection bug !!!!
		}
		
		if(!this.iconover) {
			// Rétabli le speed original du magicwheell
			if(this.speed.round(1) == 0.1)
				this.speed = 0.1;
			else if(this.speed > 0.1)
				this.speed = this.speed - 0.1;
			else if(this.speed < 0.1)
				this.speed = this.speed + 0.1;
				
			this.counter = this.counter + (this.options.userSpeed * this.speed);
		}
	}
});