/*
*	MooPlayer
*	
*	Mootools video abstraction layer that makes it easy to work with video / audio
*	
*	Adam Fisher 2008
*	
*	Notes: designed with flowPlayer in mind:
*	http://flowplayer.org/
*	
*	requires flashembed or mooflashembed
*	http://flowplayer.org/tools/flash-embed.html
*	
*	MIT style licence
*/

var callbacks = ['onFlowPlayerReady', 'onClipDone', 'onClipChanged', 'onLoadBegin', 'onStreamNotFound', 'onPlay', 'onStop', 'onPause', 'onResume', 'onCuePoint', 'onStartBuffering', 'onBufferFull', 'onBufferFlush', 'onMetaData'];

callbacks.each(function(callback){
	Element.Events.set(callback.substr(2).toLowerCase(), {});
	window[callback] = function(r){
		window.fireEvent(callback.substr(2).toLowerCase(), r);
	};
});

var MooPlayer = new Class({
	flashVars: {
		type: 'application/x-shockwave-flash',
		pluginspage: 'http://www.adobe.com/go/getflashplayer',
		quality: 'high',
		allowscriptaccess: 'always',
		allowfullscreen: false,
		width: 320,
		height: 240,
		bgcolor: '#000000',
		onFail: $empty
	},
	
	playerVars: {
		autoPlay: false,
		loop: false,
		autoRewind: true,
		controlsOverVideo:'ease',
		initialScale: 'scale',
		autoBuffering: true,
		useNativeFullScreen: true,
		usePlayOverlay: true,
		showMenu: false,
		showPlayButton: true,
		controlBarGloss:'low',
		showFullScreenButton: false,
		menuItems: '[1, 1, 1, 1, 0, 0, 0]'
	},
	
	initialize: function(container, flashVars, playlist, controls, thumb, playerVars){
		flashVars = $type(flashVars) == 'string' ? {src: flashVars} : flashVars;
		playerVars = $type(playerVars) == 'string' ? {videoFile: playerVars} : playerVars;
		
		if(controls){
			this.createControls(controls);
			this.playerVars.showPlayButton = false;
		}
		
		this.playerVars = $merge(this.playerVars, playerVars);
		this.flashVars = $merge(this.flashVars, flashVars);
		this.container = container;
		this.thumb = thumb || this.playerVars.splashImageFile;
		this.current = 0;
		this.ready = false;
		this.playing = false;
		this.stack = [];
		this.playlist = [];
		
		if(this.playerVars.videoFile){
			this.playlist.push({url: this.playerVars.videoFile});
			if(this.playerVars.splashFileImage){
				this.playlist[0].thumb = this.playerVars.splashFileImage;
			}
		}
		if(playlist){
			this.makePlaylist(playlist);
		}
		delete this.playerVars.splashImageFile;
		delete this.playerVars.videoFile;
		
		window.addEvent('flowplayerready', function(c){
			if(this.api.getVersion()){
				this.ready = true;
				if(this.stack){
					this.stack.each(function(fn){
						fn.delay(50, this);
					}.bind(this));
					this.stack = [];
				}
			}
		}.bind(this));

		this.injectVideo(0);
	},
	
	injectVideo: function(i){
		this.ready = false;
		this.playing = false;
		
		var playlist = [];
		var videoFile = this.playlist[i].url;
		var thumbFile = this.playlist[i].thumb || this.thumb;
		
		if(thumbFile){
			playlist.push({url: thumbFile, overlayId: 'play'});
		}
		playlist.push({url: videoFile});
		
		this.api = flashembed(this.container, this.flashVars, {config: $merge(this.playerVars, {playList: playlist})});
		this.current = i;
	},
		
	makePlaylist: function(target){
		switch($type(target)){
			case "object":
				this.playlist = [target];
				break;
			case "array":
				this.playlist = target;
				break;
			case "string":
				if(target.test(/^\.|^#/)){
					var links = $$(target);
					links.each(function(link, i){
						this.addLink(link, i);
					}.bind(this));
					break;
				} else if(!$(target)){
					if(target != this.playerVars.videoFile){
						this.playlist.push({url:target});
					}
					break;
				}
			case "element":
				var list = $(target);
				if(list.get('tag') == 'ul'){
					var lis = list.getElements('li');
					lis.each(function(li, i){
						var a = li.getElement('a.play') || li.getElement('a');
						if(a){
							this.addLink(a, i);
						}
					}.bind(this));
					break;
				}
			default:
				return false;
		}
	},
	
	addLink: function(link, i){
		this.playlist.push({url:link.href});
		if(this.thumb){
			this.playlist[this.playlist.length - 1].thumb = this.thumb;
		}
		var j = this.playlist.length - 1;
		$(link).addEvent('click', function(e){
			new Event(e).stop();
			this.play(j);
		}.bind(this));
	},
	
	createControls: function(controls){
		var valid = ['play', 'pause', 'toggle', 'forward', 'backwards', 'stop', 'prev', 'next'];
		$H(controls).each(function(control, name){
			if(valid.contains(name) && $(control)){
				$(control).addEvent('click', function(e){
					new Event(e).stop();
					this[name]();
				}.bind(this));
			}
		}.bind(this));
	},
	
	remote: function(method, args){
		if(this.api.getVersion()){
			return this.api[method](args) || this;
		} else{
			//this.stack.push(function(args){this.api[method](args);});
			this.remote.delay(300, this, [method, args]);
			return false;
		}
	},
	
	play: function(i){
		if($chk(i) && i != this.current){
			this.injectVideo(i);
			this.stack.push(this.play);
		} else{
			this.remote('DoPlay');
		}
		return this;
	},
	
	pause: function(){
		this.remote('Pause');
		return this;
	},
	
	toggle: function(){
		if(this.api.getVersion()){
			this.remote('getIsPlaying') === true ? this.pause() : this.play();
		} else{
			this.toggle.delay(300, this);
		}
		return this;
	},
	
	seek: function(time){
		var duration = this.remote('getDuration');
		return $type(duration) == "number" ? this.remote('Seek', time.limit(0, duration.floor())) : false;
	},
	
	move: function(inc, dir){
		inc = inc || 5;
		var time = this.remote('getTime');
		return $chk(time) ? this.seek(time.toFloat() + (inc * dir)) : false;
	},
	
	forward: function(inc){
		this.move(inc, 1);
		return this;
	},
	
	backwards: function(inc){
		this.move(inc, -1);
		return this;
	},
	
	stop: function(){
		this.remote('DoStop');
		return this;
	},
	
	next: function(){
		this.play((this.current + 1).mod(this.playlist.length));
	},
	
	prev: function(){
		this.play((this.current - 1).mod(this.playlist.length));
	}
});
