/**
 * YouTubePlayer.js - A YouTube Chromeless Player class
 * 
 * @version 1.0
 * @author Maurice Snip <mauricesnip at hotmail dot com>
 * @uses swfobject.js <http://code.google.com/p/swfobject/>
 */
var YouTubePlayer = function(pId, options) {
	
	/**
	 * Requirements
	 */
	if(typeof swfobject.embedSWF == 'undefined') {
		throw 'YouTubePlayer requires SWFObject 2.0 or higher to work!';
	}
	
	if(!/^[A-Za-z0-9\_]+$/.test(pId)) {
		throw 'The YouTube Player ID can only contain A-Z a-z 0-9 and _ (underscores). The ID being used: ' + pId;
	}
	
	/**
	 * Private properties
	 */
	var self = this;
	
	/**
	 * Public properties
	 */
	this.pId = pId;
	
	this.player = false;
	
	this.state = -1;
	
	/**
	 * Extend the YouTubePlayer object with option properties
	 */
	if(typeof options != 'undefined') {
		for(prop in options) {
			this[prop] = options[prop];
		}
	}
	
	/**
	 * onYouTubePlayerReady event handler
	 * 
	 * @scope window
	 */
	this.playerReady = function(playerId) {
		if(self.pId == playerId) {
			self.player = document.getElementById(playerId);
			
			self.addEventListener('onStateChange', self.pId + 'onStateChange');
			
			if(self.onReady) {
				self.onReady(self.player);
			}
			
			if(self.videoId && self.autoPlay) {
				self.loadVideoById(self.videoId);
			}
			else if(self.videoId) {
				self.cueVideoById(self.videoId);
			}
			
			if(self.muted) {
				self.mute();
			}
			else {
				self.unMute();
				self.setVolume(100);
			}
		}
	};
	
	/**
	 * onStateChange event handler
	 * 
	 * @scope window
	 */
	this.stateChange = function(state) {
		self.state = state;
		
		if(state === 0 && self.onEnd) {
			self.onEnd(self.player);
		}
		else if(state === 1 && self.onPlay) {
			self.onPlay(self.player);
		}
		else if(state === 2 && self.onPause) {
			self.onPause(self.player);
		}
		else if(state === 3 && self.onBuffering) {
			self.onBuffering(self.player);
		}
		else if(state === 5 && self.onCue) {
			self.onCue(self.player);
		}
	};
	
	/**
	 * onError event handler
	 * 
	 * @scope window
	 */
	this.error = function(error) {
		if(error === 100 && self.onNotFoundError) {
			self.onNotFoundError(self.player);
		}
		else if((error === 101 || error === 150 ) && self.onNoEmbedError) {
			self.onNoEmbedError(self.player);
		}
	};
	
	/**
	 * Multiple player magic, inspired by YtMooPlayer
	 * 
	 * The onYouTubePlayerReady function is called from the window scope,
	 * so we declare it as window.onYouTubePlayerReady. Since other
	 * YouTubePlayer instances might be floating around, we have to check
	 * wheter or not the onYouTubePlayerReady is declared yet. If so,
	 * we call it in our newly declared onYouTubePlayerReady function.
	 */
	var oldOnYouTubePlayerReady = window.onYouTubePlayerReady || false;
	
	if(typeof oldOnYouTubePlayerReady == 'function') {
		window.onYouTubePlayerReady = function(playerId) {
			oldOnYouTubePlayerReady(playerId);
			self.playerReady(playerId);
		};
	}
	else {
		window.onYouTubePlayerReady = this.playerReady;
	}
	
	/**
	 * Map <pId>onStateChange to the onStateChange event handler
	 */
	window[this.pId + 'onStateChange'] = this.stateChange;
	
	/**
	 * Map <pId>onError to the onError event handler
	 */
	window[this.pId + 'onError'] = this.error;
	
	/**
	 * Embed the player
	 */
	swfobject.embedSWF('http://www.youtube.com/apiplayer?enablejsapi=1&version=3&playerapiid=' + pId, pId, (this.width || 320), (this.height || 240), '8', null, null, { allowScriptAccess: 'always', bgcolor: '#000000', wmode: 'transparent' }, { id: pId });
};

/**
 * Public API
 */
YouTubePlayer.prototype = {
	cueVideoById: function(videoId, startSeconds, suggestedQuality) {
		this.player.cueVideoById(videoId, startSeconds, suggestedQuality);
	},
	
	loadVideoById: function(videoId, startSeconds, suggestedQuality) {
		this.player.loadVideoById(videoId, startSeconds, suggestedQuality);
	},
	
	playVideo: function() {
		this.player.playVideo();
	},
	
	pauseVideo: function() {
		this.player.pauseVideo();
	},
	
	togglePlay: function() {
		this.getPlayerState() === 1 ? this.pauseVideo() : this.playVideo();
	},
	
	stopVideo: function() {
		this.player.stopVideo();
	},
	
	seekTo: function(seconds, allowSeekAhead) {
		this.player.seekTo(seconds, allowSeekAhead);
	},
	
	clearVideo: function() {
		this.player.clearVideo();
	},
	
	mute: function() {
		this.player.mute();
	},
	
	unMute: function() {
		this.player.unMute();
	},
	
	isMuted: function() {
		return this.player.isMuted();
	},
	
	toggleMute: function() {
		this.isMuted() ? this.unMute() : this.mute();
	},
	
	setVolume: function(v) {
		this.player.setVolume(v);
	},
	
	getVolume: function() {
		return this.player.getVolume();
	},
	
	setSize: function(width, height) {
		this.player.setSize(width, height);
	},
	
	getVideoBytesLoaded: function() {
		return this.player.getVideoBytesLoaded();
	},
	
	getVideoBytesTotal: function() {
		return this.player.getVideoBytesTotal();
	},
	
	getVideoStartBytes: function() {
		return this.player.getVideoStartBytes();
	},
	
	getPlayerState: function() {
		return this.player.getPlayerState();
	},
	
	getCurrentTime: function() {
		return this.player.getCurrentTime();
	},
	
	getDuration: function() {
		return this.player.getDuration();
	},
	
	getVideoUrl: function() {
		return this.player.getVideoUrl();
	},
	
	getVideoEmbedCode: function() {
		return this.player.getVideoEmbedCode();
	},
	
	addEventListener: function(event, listener) {
		this.player.addEventListener(event, listener);
	}
};

