/**
 *	Object: Aktor
 */
var Aktor = {
	Name: 'Aktor',
	Codename: 'Grizzly',
	Version: '1.0',
	Build: {
		Date: '20100829-1408',
		Release: 'beta'
	},
	Authors: [
		{ Name: 'Robin Grass', Email: 'robin.grass@davelo.se' }
	]
};



/**
 *	Object: Aktor.currentChrome
 */
Aktor.currentChrome = null;



/**
 *	Object: Aktor.currentInstance
 */
Aktor.currentInstance = null;



/**
 *	Function: Aktor.setInstance
 */
Aktor.setInstance = function(instance) {
	Aktor.currentInstance = instance;
};


/**
 *	Object: Aktor.Events
 *
 *	These events are fired from Flash.
 */
Aktor.Events = {
	
	onCreate: function() { 
		Aktor.currentInstance._onCreate();
	},
	
	onDestroy: function() {
		Aktor.currentInstance._onDestroy();
	},
	
	onAttach: function() {
		Aktor.currentInstance._onAttach();
	},
	
	onDetach: function() {
		Aktor.currentInstance._onDetach();
	},
	
	onLoad: function(mediaURL, width, height) {
		Aktor.currentInstance._onLoad(mediaURL, width, height);
	},
	
	onUnload: function() {
		Aktor.currentInstance._onUnload();
	},
	
	onBuffer: function() {
		Aktor.currentInstance._onBuffer();
	},
	
	onBufferChange: function() {
		Aktor.currentInstance._onBufferChange();
	},
	
	onError: function(errorType, errorMessage) {
		Aktor.currentInstance._onError(errorType, errorMessage);
	},
	
	onPlay: function() {
		Aktor.currentInstance._onPlay();
	},
	
	onPause: function() {
		Aktor.currentInstance._onPause();
	},
	
	onStop: function() {
		Aktor.currentInstance._onStop();
	},
	
	onPlaybackEnd: function() {
		Aktor.currentInstance._onPlaybackEnd();
	},
	
	onSeek: function(seconds) {
		Aktor.currentInstance._onSeek(seconds);
	},
	
	onTimeUpdate: function(seconds) {
		Aktor.currentInstance._onTimeUpdate(seconds);
	},
	
	onTimeEvent: function(seconds) {
		Aktor.currentInstance._onTimeEvent(seconds);
	},
	
	onTimeDuration: function(seconds) {
		Aktor.currentInstance._onTimeDuration(seconds);
	},
	
	onVolumeUpdate: function(volume) {
		Aktor.currentInstance._onVolumeUpdate(volume);
	},
	
	onSizeUpdate: function(width, height) {
		Aktor.currentInstance._onSizeUpdate(width, height);
	},

	onBytesTotal: function(bytesTotal) {
		Aktor.currentInstance._onBytesTotal(bytesTotal);
	},
	
	onBytesLoaded: function(bytesLoaded) {
		Aktor.currentInstance._onBytesLoaded(bytesLoaded);
	},
	
	onFullyLoaded: function() {
		Aktor.currentInstance._onFullyLoaded();
	}

};



/**
 *	Abstract Class: Aktor.PlayerAbstract
 */
Aktor.PlayerAbstract = new Class({

	Implements: [Options, Events],
	
	options: {
		onCreate: nil,
		onDestroy: nil,
		onAttach: nil,
		onDetach: nil,
		onLoad: nil,
		onUnload: nil,
		onBuffer: nil,
		onBufferChange: nil,
		onError: nil,
		onPlay: nil,
		onPause: nil,
		onStop: nil,
		onSeek: nil,
		onTimeUpdate: nil,
		onTimeDuration: nil,
		onTimeEvent: nil,
		onVolumeUpdate: nil,
		onSizeUpdate: nil,
		onBytesTotal: nil,
		onBytesLoaded: nil,
		onFullyLoaded: nil,
		onChromeCreate: nil,
		onChromeDestroy: nil
	},
	
	timeline: nil,
	
	chrome: nil,
	
	setTimeline: function(timeline) {
		this.timeline = timeline;
	},
	
	setChrome: function(chrome) {
		this.chrome = chrome;
	},
	
	loadChrome: function() {
		var self = this;
		if(this.chrome) {
			var request = new Request.JSON({
				url: 'chrome/' + self.chrome + '/manifest.json',
				method: 'get',
				onSuccess: function(response) {
					Aktor.chromeResources = response;
					Asset.javascript(response.Resources.javascript);
				},
				onFailure: function() {
					alert('Could not load Aktor chrome!');
				}
			}).send();
		}
	},
	
	unloadChrome: function() {
		if(Aktor.currentChrome)
			Aktor.currentChrome.destroy();
	},
	
	_onCreate: function() { 
		this.fireEvent('onCreate');
	},
	
	_onDestroy: function() {
		this.fireEvent('onDestroy');
	},
	
	_onAttach: function() {
		this.fireEvent('onAttach');
	},
	
	_onDetach: function() {
		this.fireEvent('onDetach');
	},
	
	_onLoad: function(mediaURL) {
		this.fireEvent('onLoad', mediaURL);
		this.unloadChrome();
		this.loadChrome();
	},
	
	_onUnload: function() {
		this.fireEvent('onUnload');
		this.unloadChrome();
	},
	
	_onBuffer: function() {
		this.fireEvent('onBuffer');
	},
	
	_onBufferChange: function() {
		this.fireEvent('onBufferChange');
	},
	
	_onError: function(errorType, errorMessage) {
		this.fireEvent('onError', [errorType, errorMessage]);
	},
	
	_onPlay: function() {
		this.fireEvent('onPlay');
	},
	
	_onPause: function() {
		this.fireEvent('onPause');
	},
	
	_onStop: function() {
		this.fireEvent('onStop');
	},
	
	_onSeek: function(time) {
		this.fireEvent('onSeek', time);
	},
	
	_onTimeUpdate: function(time) {
		this.fireEvent('onTimeUpdate', time);
	},
	
	_onTimeDuration: function(time) {
		this.fireEvent('onTimeDuration', time);
	},
	
	_onTimeEvent: function(time) {
		var time = time.round(1);
		if(this.timeline) {
			var obj = this.timeline[String(time)];
			if(obj) {
				if(typeOf(obj) == 'function') {
					this.fireEvent('onTimeEvent', Number(time));
					obj.attempt();
				} else if(typeOf(obj) == 'object') {
					if(obj.callback && obj.arguments) {
						this.fireEvent('onTimeEvent', Number(time));
						obj.callback.attempt(obj.arguments);
					}
				}
			}
		}
	},
	
	_onVolumeUpdate: function(volume) {
		this.fireEvent('onVolumeUpdate', volume);
	},
	
	_onSizeUpdate: function(width, height) {
		this.fireEvent('onSizeUpdate', [width, height]);
	},

	_onBytesTotal: function(bytesTotal) {
		this.fireEvent('onBytesTotal', bytesTotal);
	},
	
	_onBytesLoaded: function(bytesLoaded) {
		this.fireEvent('onBytesLoaded', bytesLoaded);
	},
	
	_onFullyLoaded: function() {
		this.fireEvent('onFullyLoaded');
	},
	
	_onPlaybackEnd: function() {
		this.fireEvent('onPlaybackEnd');
	}

});



/**
 *	Abstract Class: Aktor.ApiAbstract
 */
Aktor.ApiAbstract = new Class({
	
	Implements: [Options, Events, Aktor.PlayerAbstract],
	
	options: {
		unsupportedBrowserVersion: 'Your browser is outdated, please update to a newer version.',
		unsupportedFlashVersion: 'Flash 10 is required for Aktor to work.'
	},
	
	initialize: function(options) {
		this.setOptions(options);
		Aktor.setInstance(this);
	},
	
	toElement: function() {
		if(!Browser.Engine.trident)
			return this.$swiff.toElement();
		else {
			return document[this.options.player.id];
		}
	},
	
	toParent: function() {
		return this.$swiff.options.container;
	},
	
	toChrome: function() {
		return this.toParent().getElement('div');
	},
	
	checkCompability: function() {
		
		if(Browser.ie6) {
			this.toParent().empty();
			new Element('p', {
				'html': this.options.unsupportedBrowserVersion,
				'class': 'unsupported-browser'
			}).inject(this.toParent());
		}
		
		if(Browser.Plugins.Flash < 10) {
			this.toParent().empty();
			new Element('p', {
				'html': this.options.unsupportedBrowserVersion,
				'class': 'unsupported-browser'
			}).inject(this.toParent());
		}
		
		if(Browser.firefox)
			this.toParent().addClass('firefox');
		if(Browser.ie7)
			this.toParent().addClass('ie7');
		if(Browser.ie8)
			this.toParent().addClass('ie8');
		if(Browser.chrome)
			this.toParent().addClass('chrome');
	},
	
	create: function(parent, properties, position) {
		this.$element = new Element('div', {
			id: this.options.id,
			styles: Object.merge(this.options.styles, { 'position': 'relative' })
		}).inject(parent, position || 'bottom');
		
		var properties = Object.merge(this.options.flash, {
			id: this.options.player.id,
			container: this.$element
		});
		
		this.$swiff = new Swiff(this.options.player.engine, properties);
		this.checkCompability();
		
		this._onCreate();
	},
	
	destroy: function() {
		if(this.$element) {
			this.$element.empty();
			this.$element.destroy();
			this._onDestroy();
		}
	},
	
	attach: function(parent, position) {
		if(typeOf(parent) == 'element')
			parent.grab(this.$element, position || 'bottom');
		this.$element = parent;
		
		this._onAttach();
	},
	
	detach: function() {
		this.$element = this.$element.dispose();
		this._onDetach();
	},
	
	load: function(mediaURL, width, height) {
		this.toElement().load(mediaURL, width, height);
		this.setSize(width, height);
	},
	
	unload: function() {
		this.toElement().load('', 1, 1);
		this._onUnload();
	},
	
	setSize: function(width, height) {
		this.toElement().setSize(width, height);
		if(Browser.ie) {
			this.toElement().setAttribute('width', width);
			this.toElement().setAttribute('height', height);
		} else {
			this.toElement().set({
				'width': width,
				'height': height
			});
		}
	},
	
	getSize: function() {
		return new Hash(this.toElement().getProperties('width', 'height')).map(function(value, key) {
			return value.toInt();
		});
	},
	
	getElapsed: function() {
		return this.toElement().getElapsed().round(2);
	},
	
	getElapsedPercent: function() {
		return ((this.getElapsed() / this.getDuration()) * 100).round();
	},
	
	getDuration: function() {
		return this.toElement().getDuration().round(2);
	},
	
	getRemaining: function() {
		return (this.getElapsed() - this.getDuration()).round(2);
	},
	
	setVolume: function(volume) {
		this.toElement().setVolume(volume.limit(0, 100));
	},
	
	getVolume: function() {
		return this.toElement().getVolume();
	},
	
	toggleMute: function() {
		return this.toElement().toggleMute();
	},
	
	play: function() {
		return this.toElement().startMedia();
	},
	
	togglePlay: function() {
		return this.toElement().togglePlay();
	},
	
	pause: function() {
		return this.toElement().pause();
	},
	
	stop: function() {
		return this.toElement().rewindMedia();
	},
	
	seek: function(seconds) {
		return this.toElement().seek(seconds.limit(0, this.getDuration()));
	},
	
	setTime: function(seconds) {
		this.seek(seconds);
		this.pause();
	},
	
	isPlaying: function() {
		var paused = this.toElement().isPaused();
		if(paused)
			return false;
		else return true;
	},
	
	isMuted: function() {
		return this.toElement().isMuted();
	},
	
	confirm: function(options) {
		
		options = Object.merge({ text: 'Hello World!', confirmText: 'Ok!', cancelText: 'Cancel' }, options);
		
		var confirm = new Element('div', {
			'class': 'confirm-box'
		}).inject(this.toParent());
		
		var p = new Element('p', {
			'html': options.text
		}).inject(confirm);
		
		var buttons = new Element('div', {
			'class': 'clearfix'
		}).inject(confirm);
		
		var confirm_button = new Element('a', {
			'href': '#',
			'html': options.confirmText,
			'class': 'confirm-button',
			'events': {
				'click': function(event) {
					confirm.destroy();
					if(options.onConfirm && typeOf(options.onConfirm) == 'function')
						options.onConfirm.attempt();
				}
			}
		}).inject(buttons);
		
		var cancel_button = new Element('a', {
			'href': '#',
			'html': options.cancelText,
			'class': 'cancel-button',
			'events': {
				'click': function(event) {
					confirm.destroy();
					if(options.onCancel && typeOf(options.onCancel) == 'function')
						options.onCancel.attempt();
				}
			}
		}).inject(buttons);
	}

});


/**
 *	Class: Aktor.Player
 */
Aktor.Player = new Class({

	Extends: Aktor.ApiAbstract,
	
	options: {
		id: 'aktor_player',
		styles: {},
		flash: {},
		player: {
			id: 'aktor_player_object',
			engine: 'AktorPlayer.swf'
		}
	},
	
	initialize: function(options) {
		this.parent(options);
	}

});
