// VideoPlayer
var HtmlPlayer = new Class({

	Implements: [Events, Options],
	
	options: {
		videoClass: '', //videoClass: 'video',
		videoId: '',
		fallbackId: '',
		injectionTarget: undefined,
		siteUrl: '',
		sources: undefined,
		poster: '',
		width: -1,
		height: -1,
		params: null,
		
		quality: 'SD',

		autoplay: false,
		
		enableControls: false,
		controlsEnabled: false,
		
		enableInfoScreen: false,
		infoScreenEnabled: false,
		
		enablePoster: false,
		posterEnabled: false,
		
		volume: 1,
		muted: false,
		playing: false,
		loading: true,
		timestamp: 0,
		duration: undefined,
		startTime: undefined,
		qualityChanged: false,
		
		/* HtmlPlayer spezifisch: */
		videoControlsClass: 'videoControls',
		progressBarClass: 'progressBar',
		volumeBarClass: 'volumeBar',
		volumeBarContainerClass: 'volumeBarContainer',
		
		videoInfoScreenClass: 'videoInfoScreen',

		videoPosterClass: 'videoPoster',
		
		knobClass: 'knob',
		barClass: 'bar',
		
		volumeStep: 0.1,
	},
	
	media_events: ["loadstart", "progress", "suspend", "abort", "error", "emptied", "stalled", "play",
	              "pause", "loadedmetadata", "loadeddata", "waiting", "playing", "canplay",	"canplaythrough",
	              "seeking", "seeked", "timeupdate", "ended", "ratechange", "durationchange", "volumechange"],
	
	infoScreenFX: undefined,
	controlsFx: undefined,
	volumeBarContainerFX: undefined,
	
	/**
	 * @type {Function}
	 */
	eventDelegate : undefined,
	//videoElementLoadeddataDelegate : undefined,
	
	infoScreenPlayDelegate : undefined,
	infoScreenPauseDelegate : undefined,
	infoScreenTimeupdateDelegate : undefined,
	
	controlsVolumechangeDelegate : undefined,
	controlsTimeupdateDelegate : undefined,

	initialize: function(options){
		this.setOptions(options);
	
		if($chk(this.options.injectionTarget)) this.options.injectionTarget.addClass('html_player');
		this.element = new Element('div', {'class': 'wrapper'});
		
		this.videoElement = new Element('video', {'class': this.options.videoClass})
			.setStyle('visibility', 'visible')
			.addEvents({
				'click': function () {
					this.togglePlay();
				}.bind(this)
			}); // 'src': options.sources[0].src

		this.videoElement.autoplay = this.options.autoplay;
		this.videoElement.preload = 'preload';
		this.videoElement.controls = !this.options.enableControls;
		this.videoElement.loop = false;
		this.videoElement.volume = this.options.volume;
		this.videoElement.muted = this.options.muted;

		this.videoElement.inject(this.element);
		
		this._build();		
		
		/*
		if(!this.options.injectionTarget){
			return this.toElement();
		}
		*/
	},
	
	toElement: function(){ 
		return this.element; 
	},
	
	getVideoElement: function() {
		return this.videoElement;
	},
	
	setNewOptions: function(options) {
		this.setOptions(options);
		this._build();
		//if(this.options.autoplay) this.play();
	},
	
	/*
	setSource: function(sources) {
		this.stop();
		this.options.sources = sources;
		this.videoElement.getChildren().destroy();
		
		$each(sources, function(source){
			var sourceElement = new Element('source', {'src': source.src, 'type': source.type});
			sourceElement.inject(this.videoElement);
		}.bind(this));		
	},
	
	setInjectionTarget: function(injectionTarget) {
		this.stop();
		this.options.injectionTarget = injectionTarget;
		if ($chk(this.options.injectionTarget.getElement('.videoPlayer'))) {
			this.options.injectionTarget.getElement('.videoPlayer').dispose();
		}
		this.element.inject(injectionTarget);
	},
	*/
	
	_build: function() {
		if(!$chk(this.options.injectionTarget)) return;
		
		var fallbackElement = $(this.options.fallbackId);
		if($chk(fallbackElement)) fallbackElement.destroy();
		
		this.stop();
		
		this.videoElement.setProperty('poster', this.options.poster);
		
		this._detachEvents();
		this._attachEvents();
		
		this._injectSources();
		
		//this.options.playing = this.options.autoplay;
		
		this.element.inject(this.options.injectionTarget);

		if(this.options.enableInfoScreen) {
			this._buildInfoScreen();
		}
		
		if(this.options.enableControls) {
			this._buildControls();
		}
		
		if(this.options.enablePoster) {
			this._buildPoster();
		}
	},
	
	_destroy: function() {
		this.stop();
		
		this._detachEvents();
		
		this._destroyInfoScreen();
		this._destroyControls();
		
		this.element.destroy();
		
		this.videoElement.getChildren().destroy();
		this.videoElement.destroy();
		
		delete this.element;
		delete this.videoElement;		
	},
	
	_injectSources: function() {
		this.pause();
		this.videoElement.getChildren().dispose();
		this.videoElement.setProperty('html', '<p>Your user agent does not support the HTML5 Video element.</p>');
		
		var quality = this.options.quality;
		
		Object.each(this.options.sources, function(value, key, obj) {
			if(value.plattform == 'html') {
				var sourceElement = new Element('source', {'src': value['src_' + quality.toLowerCase()], 'type': value.type}); /* Type muss für Android-Kompatiblität entfernt werden! */
				//var sourceElement = new Element('source', {'src': 'http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4', 'type': value.type});
				sourceElement.inject(this.videoElement, 'top');
				//console.info(value['src_' + quality.toLowerCase()]);
				//console.info('Type: '+ value.type + ' CanPlay: ' + this.videoElement.canPlayType(value.type));
				//console.info(value['src_' + quality.toLowerCase()]);
			}
		}, this);
		
		this.videoElement.load();
		//this.goToTimestamp(this.options.timestamp);
		//if(this.options.playing) this.videoElement.play();
		
		//console.log(this.options.playing);
		//console.dir(this.videoElement);
	},
	
	_attachEvents: function() {
		if(this.eventDelegate === undefined) {
			this.eventDelegate = this._eventHandler.bind(this);
		}
		
		for (var i = 0; i < this.media_events.length; i++) { 
			this.videoElement.addEventListener(this.media_events[i], this.eventDelegate, false);
		}
		
		/*
		if(this.videoElementLoadeddataDelegate === undefined) {
			this.videoElementLoadeddataDelegate = this._videoElementLoadeddataHandler.bind(this);
		}

		this.videoElement.addEventListener('durationchange', this.videoElementLoadeddataDelegate, false);
		*/
	},
	
	_detachEvents: function() {
		for (var i = 0; i < this.media_events.length; i++) { 
			this.videoElement.removeEventListener(this.media_events[i], this.eventDelegate, false);
		}
		
		//this.videoElement.removeEventListener('durationchange', this.videoElementLoadeddataDelegate, false);
	},
	
	_eventHandler: function(e) {
		//console.log('Type: ' + e.type);
		//console.log(this.videoElement.networkState + ' - ' + this.videoElement.NETWORK_LOADING);
		//console.log(this.videoElement.currentTime + ' - ' + this.options.timestamp);
		switch(e.type) {
			case "pause":
				if(this.options.qualityChanged) return;
				
				if(this.options.controlsEnabled) {
					this.playButton.removeClass('pause');
					this.playButton.addClass('play');	
				}
				if(this.options.infoScreenEnabled) {
					
				}
				
				this.options.playing = false;
				break;	
			case "play":
				if(this.options.controlsEnabled) {
					this.playButton.removeClass('play');
					this.playButton.addClass('pause');
				}
				if(this.options.infoScreenEnabled) {
					
				}

				this.options.playing = true;
				break;
			case "loadstart":
				if(this.options.controlsEnabled) {
					this.playButton.removeClass('pause');
					this.playButton.addClass('play');
				}
				//this.options.playing = false;
				break;
			case "timeupdate":
				if(e.target.currentTime > 0) {
					this.options.timestamp = e.target.currentTime;
				}
				break;
			case "progress":
				break;
			case "durationchange":
				this.options.duration = e.target.duration;
				this.options.startTime = e.target.startTime;
				
				this.videoElement.muted = this.options.muted;
				this.videoElement.volume = this.options.volume;
				//this.videoElement.currentTime = this.options.timestamp;
				if(this.options.qualityChanged) {
					//console.log('Timestamp: '+ this.options.timestamp);
					//console.log('Reset: '+ this.options.muted + ' - ' + this.options.volume);

					this.goToTimestamp(this.options.timestamp);
					if(this.options.playing) {
						//console.log('PLAY!');
						this.videoElement.play();
					}
					
					this.options.qualityChanged = false;
				}
				break;
			case "error":
				//console.dir(e);
				break;
			case "canplay":
				break;
			case "volumechange":
				this.options.volume = this.videoElement.volume;
				this.options.muted = this.videoElement.muted;		
				//console.log('Reset: '+ this.options.muted + ' - ' + this.options.volume);
				break;
			default:
				break;
		}
	},
	
	/*
	_videoElementLoadeddataHandler: function(e) {
		this.options.duration = e.target.duration;
		this.options.startTime = e.target.startTime;
		this.volume = e.target.volume;
		//this.volumeSlider.fireEvent('tick', this.volumeSlider.toPosition(this.volume * this.pSliderOptions.steps));
	},
	*/
	
	togglePlay: function(){
		/*
		this.playButton.toggleClass('play');
		this.playButton.toggleClass('pause');
		*/
		if(this.options.playing === true){
			this.pause();
		} else {
			this.play();
		}
	},
	
	toggleQuality: function(){
		this.qualityButton.toggleClass('SD');
		this.qualityButton.toggleClass('HD');

		switch(this.options.quality) {
			case 'SD':				
				this.options.quality = 'HD';
				break;
			case 'HD':				
				this.options.quality = 'SD';
			default:
				break;
		}
		
		this.options.qualityChanged = true;
		this._injectSources();
	},
	
	/* Nicht implementiert */
	toggleFullscreen: function () {
		this.fullscreenButton.toggleClass('fullscreenOn');
		this.fullscreenButton.toggleClass('fullscreenOff');
	},
		
	play: function(){
		this.videoElement.play();
		//this.options.playing = true;
	},
	
	pause: function(){
		this.videoElement.pause();
		//this.options.playing = false;
	},

	stop: function(){
		this.pause(true);
		this.goToTimestamp(0);
	},
	
	goToTimestamp: function(timestamp){
		//console.log(timestamp);
		if(timestamp < this.startTime){
			timestamp = this.startTime;
		}

		if(this.videoElement.readyState != this.videoElement.HAVE_NOTHING) {
			this.videoElement.currentTime = timestamp;
		}
	},
	
	goToPercent: function(percent) {
		this.goToTimestamp(percent * this.videoElement.duration);
	},
	
	volumeUp: function(){
		this.setVolume(this.videoElement.volume + this.options.volumeStep);
	},
	
	volumeDown: function(){
		this.setVolume(this.videoElement.volume - this.options.volumeStep);
	},
	
	setVolume: function(value){
		if(value < 0){
			value = 0;
		} else if(value > 1) {
			value = 1;
		}
		
		this.videoElement.volume = value;
	},
	
	toggleMute: function(){
		this.volumeButton.toggleClass('volumeOn');
		this.volumeButton.toggleClass('volumeOff');
		
		var value = !this.videoElement.muted;
		this.videoElement.muted = value;
	},
	
	enableControls: function(flag) {
		if(flag) {
			this._buildControls();
		}
		else {
			this._destroyControls();
		}
	},
	
	_buildControls: function(){
		if(this.options.controlsEnabled) {
			this._destroyControls();
		}		
		this.options.controlsEnabled = true;
		
		this.controls = new Element('div', {'class': this.options.videoControlsClass});
		this.controls.inject(this.element, 'bottom');
		
		if(this.controlsFX === undefined) {
			this.controlsFX = new Fx.Morph(this.controls, {'duration': 300});
		}
		
		if(this.videoElement.autoplay) this.playButton = new Button({'class': 'pause button', 'callback': function(){ this.togglePlay(); }.bind(this)});
		else this.playButton = new Button({'class': 'play button', 'callback': function(){ this.togglePlay(); }.bind(this)});
		
		this.qualityButton = new Button({'class': this.options.quality +' button', 'callback': function(){ this.toggleQuality(); }.bind(this)});

		//this.stopButton = new Button({'class': 'stop button', 'callback': function(){ this.stop(); }.bind(this)});
		//this.volumeUpButton = new Button({'class': 'volumeUp button', 'callback': function(){ this.volumeUp(); }.bind(this)});
		//this.volumeDownButton = new Button({'class': 'volumeDown button', 'callback': function(){ this.volumeDown(); }.bind(this)});		
		
		var progressBar = new Element('div', {'class': this.options.progressBarClass});
		this.volumeBarContainer = new Element('div', {'class': this.options.volumeBarContainerClass}).inject(this.controls);
		
		if(this.volumeBarContainerFX === undefined) {
			this.volumeBarContainerFX = new Fx.Morph(this.volumeBarContainer, {'duration': 200});
		}
		
		var volumeBar = new Element('div', {'class': this.options.volumeBarClass}).inject(this.volumeBarContainer);
		var pBar = new Element('div', {'class': this.options.barClass});
		var pKnob = new Element('div', {'class': this.options.knobClass});
		var vBar = new Element('div', {'class': this.options.barClass});
		var vKnob = new Element('div', {'class': this.options.knobClass});

		progressBar.inject(this.controls);
		this.volumeBarContainer
			.addEvents({
				'mouseleave': function() {
					this.volumeBarContainerFX.cancel();
					this.volumeBarContainerFX.start({
						'opacity': 0,
					});
				}.bind(this)
			})
			.setStyle('opacity', 0);

		pBar.inject(progressBar);
		pKnob.inject(progressBar);
		vBar.inject(volumeBar);
		vKnob.inject(volumeBar);

		//this.fullscreenButton = new Button({'class': 'fullscreenOff button', 'callback': function(){ this.toggleFullscreen(); }.bind(this)});
		this.volumeButton = new Button({'class': 'volumeOn button', 'callback': function(){	this.toggleMute(); }.bind(this)});

		this.volumeButton
		.addEvents({
			'mouseenter': function() {
				this.volumeBarContainerFX.cancel();
				this.volumeBarContainerFX.start({
					'opacity': 1,
				});
			}.bind(this)
		});

		this.pSliderOptions = {
			steps: 100,
			wheel: true
		};
		
		this.vSliderOptions = {
			steps: 100,
			wheel: true,
			mode: 'vertical',
			initialStep: this.options.volume
		};
		
		this.progressSlider = new Slider(pBar, pKnob, this.pSliderOptions);
		this.volumeSlider = new Slider(vBar, vKnob, this.vSliderOptions);
		
		this.progressSlider.addEvent('change', function(step) {
			this.goToTimestamp((step * this.options.duration) / this.pSliderOptions.steps);
		}.bind(this));
		
		this.volumeSlider.addEvent('change', function(step) {
			this.setVolume(1-(step/this.vSliderOptions.steps));
		}.bind(this));
		
		if(this.controlsVolumechangeDelegate === undefined) {
			this.controlsVolumechangeDelegate = this._controlsVolumechangeHandler.bind(this);
		}
				
		this.videoElement.addEventListener('volumechange', this.controlsVolumechangeDelegate, false);
		
		if(this.controlsTimeupdateDelegate === undefined) {
			this.controlsTimeupdateDelegate = this._controlsTimeupdateHandler.bind(this);
		}
		
		this.videoElement.addEventListener('timeupdate', this.controlsTimeupdateDelegate, false);
		
		this.playButton.inject(this.controls);
		//this.stopButton.inject(this.controls);
		//this.volumeUpButton.inject(this.controls);
		//this.volumeDownButton.inject(this.controls);
		this.volumeButton.inject(this.controls);
		this.qualityButton.inject(this.controls);
		//this.fullscreenButton.inject(this.controls);
		
		// Startinitialisierungen
		this.controls.setStyle('opacity', 0);

		this.element.addEvents({
			'mouseenter': function(){
				this.controlsFX.cancel();
				this.controlsFX.start({
					'opacity': 1,
				});
			}.bind(this),
			'mouseleave': function(){
				this.controlsFX.cancel();
				this.controlsFX.start({
					'opacity': 0,
				});
			}.bind(this)
		});
		
		this.controlsFX.cancel();
		this.controlsFX.start({
			'opacity': 1,
		});
	},
	
	_controlsVolumechangeHandler: function(e) {
		this.options.volume = e.target.volume;
		if(e.target.muted){
			this.options.volume = 0;
		}
	},
	
	_controlsTimeupdateHandler: function(e) {
		this.progressSlider.fireEvent('tick', this.progressSlider.toPosition(e.target.currentTime * this.pSliderOptions.steps) / this.options.duration);
	},
	
	_destroyControls: function() {
		if(!this.options.controlsEnabled) return;
		this.options.controlsEnabled = false;

		this.videoElement.removeEventListener('volumechange', this.controlsVolumechangeDelegate, false);
		this.videoElement.removeEventListener('timeupdate', this.controlsTimeupdateDelegate, false);
		
		this.progressSlider.removeEvents('change');
		delete this.progressSlider;
		
		this.volumeSlider.removeEvents('change');
		delete this.volumeSlider;
		
		this.element.removeEvents('mouseenter');
		this.element.removeEvents('mouseleave');
				
		this.volumeBarContainerFX.cancel();
		delete this.volumeBarContainerFX;
		
		this.volumeBarContainer.removeEvents('mouseleave');
		delete this.volumeBarContainer;
		
		this.controlsFX.cancel();
		delete this.controlsFX;
				
		this.controls.destroy();
		delete this.controls;
		delete this.playButton;
		
		this.volumeButton.removeEvents('mouseenter');
		delete this.volumeButton;
		//delete this.fullscreenButton;
	},
	
	enableInfoScreen: function(flag) {
		if(flag) {
			this._buildInfoScreen();
		}
		else {
			this._destroyInfoScreen();
		}
	},
	
	_buildInfoScreen: function() {
		if(this.options.infoScreenEnabled) return;		
		this.options.infoScreenEnabled = true;
		
		this.infoScreen = new Element('div', {'class': this.options.videoInfoScreenClass}).addEvents({
			'click': function (e) {
				this.togglePlay();
				//this.videoElement.fireEvent('click', e);
			}.bind(this)
		});
		this.infoScreen.inject(this.element, 'bottom');
		
		this.infoFieldBackground = new Element('div', {'class': 'background'})
			.setStyle('visibility', 'visible')
			.inject(this.infoScreen);
		this.infoField = new Element('div', {'class': 'infoField'})
			.setStyle('opacity', 1)
			.inject(this.infoScreen);
		
		if(Browser.ie) {
			this.infoFieldBackground.setStyle('visibility', 'hidden');
		}
		
		if(this.infoScreenFX === undefined) {
			this.infoScreenFX = new Fx.Morph(this.infoField, {'duration': 450});
		}
		
		new Element('div', {'class': 'loading fieldStatus'}).inject(this.infoField);

		if(this.infoScreenPlayDelegate === undefined) {
			this.infoScreenPlayDelegate = this._infoScreenPlayHandler.bind(this);
		}
		
		this.videoElement.addEventListener('play', this.infoScreenPlayDelegate,	false);
		
		if(this.infoScreenPauseDelegate === undefined) {
			this.infoScreenPauseDelegate = this._infoScreenPauseHandler.bind(this);
		}
		
		this.videoElement.addEventListener('pause', this.infoScreenPauseDelegate, false);
		
		if(this.infoScreenTimeupdateDelegate === undefined) {
			this.infoScreenTimeupdateDelegate = this._infoScreenTimeupdateHandler.bind(this);
		}
		
		this.videoElement.addEventListener('timeupdate', this.infoScreenTimeupdateDelegate, false);
	},
	
	_infoScreenPlayHandler: function() {
		this.infoScreen.getElement('.fieldStatus').setProperty('class', 'play fieldStatus');
		this._showInfoScreen();
	},
	
	_infoScreenPauseHandler: function() {
		this.infoScreen.getElement('.fieldStatus').setProperty('class', 'pause fieldStatus');
		this._showInfoScreen();
	},
	
	_infoScreenTimeupdateHandler: function() {
		//console.log('ReadyState: ' + this.videoElement.readyState);
		switch (this.videoElement.readyState) {
			case this.videoElement.HAVE_ENOUGH_DATA:
				if(!this.options.loading) return;
				this.infoField.setStyles({'opacity': 0, 'visibility': 'hidden'});
				this.infoFieldBackground.setStyle('visibility', 'hidden');
				this.options.loading = false;
				break;
			default:
				if(this.options.loading) return;
				this.infoScreen.getElement('.fieldStatus').setProperty('class', 'loading fieldStatus');
				this.infoField.setStyles({'opacity': 1, 'visibility': 'visible'});
				this.infoFieldBackground.setStyle('visibility', 'visible');
				this.options.loading = true;
			break;
		}	
	},
	
	_showInfoScreen: function() {
		this.infoField.setStyles({'visibility': 'visible', 'opacity': 1});
		this.infoScreenFX.cancel();
		this.infoScreenFX.start({
			'opacity': 0
		});
	},
	
	_destroyInfoScreen: function() {
		if(!this.options.infoScreenEnabled) return;
		this.options.infoScreenEnabled = false;
		
		this.videoElement.removeEventListener('timeupdate', this.infoScreenTimeupdateDelegate, false);
		this.videoElement.removeEventListener('pause', this.infoScreenPauseDelegate, false);
		this.videoElement.removeEventListener('play', this.infoScreenPlayDelegate, false);
		
		this.infoField.destroy();
		delete this.infoField;
		
		this.infoScreen.removeEvents('click');
		this.infoScreen.destroy();
		delete this.infoScreen;
		
		this.infoScreenFX.cancel();
		delete this.infoScreenFX;
	},
	
	enablePoster: function(flag) {
		if(flag) {
			this._buildPoster();
		}
		else {
			this._destroyPoster();
		}
	},
	
	_buildPoster: function() {
		if(this.options.posterEnabled) return;
		this.options.posterEnabled = true;
		
		var bg = '#000000 url('+this.options.poster+')';

		this.poster = new Element('div', {'id': 'player_preview'})
			.setStyle('background', bg)
			.addEvent('click', function(e) {
				$('player_preview').destroy();
				this.videoElement.setStyle('visibility', 'visible');
				//console.log(this.videoElement.canPlayType('video/mp4; codecs="avc1.42E01E"') + ' - ' + this.videoElement.canPlayType('video/mp4; codecs="mp4v.20.8"') + ' - ' + this.videoElement.canPlayType('video/mov'));
				this.play();
			}.bind(this));

		new Element('div', {'id' : 'player_button_play'})
			.inject(this.poster);

		this.poster.inject(this.element, 'bottom');

      //document.getElement('.teaser').addEvent('click', function() { alert("Teaser"); });
     	//$('video').addEvent('click', function() { alert("Video"); });
     	//$('video_container').addEvent('click', function() { alert("video_container"); });
     	//$('player_preview').addEvent('click', function() { alert("player_preview"); });
	},
	
	/*
	_buildPoster: function() {
		if(this.options.posterEnabled) return;
		this.options.posterEnabled = true;
		
		var bg = '#000000 url('+this.options.poster+')';
		this.poster = new Element('div', {'id': 'player_preview', 'html': '<div id="player_button_play"></div>'})
			.setStyle('background', bg)
			.addEvent('click', function() {
				$('player_preview').destroy();
				this.play();
			}.bind(this));
		this.poster.inject(this.element, 'bottom');
	},
	*/
	
	_destroyPoster: function() {
		if(!this.options.posterEnabled) return;
		this.options.posterEnabled = false;
		
		this.poster.destroy();
		delete this.poster;
	}
});
