var Video = new Class((function() {
	
	var videoFactory,
		dummyEl = new Element('div', {
			styles: {
				width: '1px',
				height: '1px',
				position: 'absolute',
				top: '0',
				left: '0',
				overflow: 'hidden'
			}
		});
		
	window.addEvent('domready', function () { dummyEl.inject(document.body); dummyEl.setStyle('visibility', 'hidden'); } );
	
	if(!!document.createElement('video').canPlayType && !Browser.Engine.presto) {
		//supports <video />
		
		if(Browser.Engine.gecko || Browser.Engine.presto) {
			//uses Ogg Theora
			videoFactory = function(src, options) {
				options.src = src + '.ogv';
				
				
				var video = new Element('video', options);
				return video;
			};
		} else {
			//uses H.264
			
			videoFactory = function(src, options) {
				options.src = src + '.mp4';
				var video = new Element('video', options);
				return video;
			};
		}
	} else {
		videoFactory = function(src, options, videoID) {
			var video,
				paramStr = 'src=' + escape(src + '.mp4'),
				swfUrl,
				stupidDiv = new Element('div', {id: videoID});
			dummyEl.appendChild(stupidDiv);
			
			for(p in options)
			{
				if(options.hasOwnProperty(p))
				{
					paramStr += '&' + p + '=' + escape(options[p]);
				}
			}
			swfUrl = '/flash/VideoPlayer2.swf?' + paramStr + '&id=' + videoID;
			
			video = swfobject.createSWF(
				{data: swfUrl, width: options.width, height: options.height},
				{allowscriptaccess: 'always', wmode: 'transparent', allowfullscreen: 'true'}, videoID);
			video.parentNode.removeChild(video);
			return video;
		};
	}
	
	//private static
	var _lastId = 0;
	function videoID() {
		return 'video_' + (++_lastId);
	}
	function isVideo(element) {
		return  element && element.tagName.toLowerCase() === 'video';
	}
	
	function getVideoHeight(element) {
		return isVideo(element) ? element.videoHeight : element.getVideoHeight();
	}
	
	function getVideoWidth(element) {
		return isVideo(element) ? element.videoWidth : element.getVideoWidth();
	}
	
	function getDuration(element) {
		//return element.getDuration();
		return isVideo(element) ? element.duration : ((element && element.getDuration) ? element.getDuration() : 1);
	}
	
	function getCurrentTime(element) {
		return isVideo(element) ? element.currentTime : ((element && element.getCurrentTime) ? element.getCurrentTime() : 0);
	}
	
	function getPaused(element) {
		return isVideo(element) ? element.paused : element.getPaused();
	}
	
	function setCurrentTime(element, time) {
		var problem;
		if(isVideo(element)) {
			try {
				element.currentTime = time;
			}
			catch(problem) {
			}
		} else {
			callExternalInterface.call(element.video, element, 'setCurrentTime', [time]);
		}
	}
	
	function addEvent() {
		if(isVideo(this.video)) {
			this.video.addEvent.apply(this.video, arguments);
		} else {
			//flash
			this.flashEventManager.addEvent.apply(this.flashEventManager, arguments);
			if (this.video.addSWFEvent)
			{
				this.video.addSWFEvent(this._swfID, arguments[0]);
			}
			else
			{
				this.eventQueue.push(function(me, args)
				{
					return function ()
					{
						me.element.addSWFEvent(me._swfID, args)
					}
				}(this, arguments[0]));
			}
		}
	}
	
	function removeEvent() {
		if(isVideo(this.video)) {
			this.video.removeEvent.apply(this.video, arguments);
		} else {
			//flash
			this.flashEventManager.removeEvent.apply(this.flashEventManager, arguments);
			//this.video.removeSWFEvent(this._swfID, arguments[0]);
		}
	}
	
	function fireEvent(eventName, eventObj) {
		if(isVideo(this.video)) {
			this.video.fireEvent(eventName, eventObj);
		} else {
			this.flashEventManager.fireEvent(eventName, eventObj);
		}
	}
	
	function callExternalInterface(object, method, arg) {
		try
		{
			if(typeof arg != 'undefined')
				object[method](arg);
			else
				object[method]();
		}
		catch(e)
		{
			if(method == 'getCurrentTime') return;
			this.eventQueue.push(function() {
				if(typeof arg != 'undefined')
					object[method](arg);
				else
					object[method]();
			});
		}
	}
	
	function formatTime(seconds) {
		var mins = Math.floor(seconds / 60),
			secs = Math.round(seconds - (mins * 60));
			
		return pad(mins) + ':' + pad(secs);
	}
	
	function pad(number) {
		return number < 10 ? '0'+number : number;
	}
	
	function fullScreenOn(el) {
		el.setStyles({
			position: 'fixed',
			top: 0,
			left: 0,
			right: 0,
			bottom:0,
			'z-index': 11,
			height: '100%',
			width: '100%'
		});
		el.getElement('video').setStyles({
			height: '100%',
			width: '100%'
		});
		$('Content').setStyle('z-index', 11);
	}
	
	function fullScreenOff(el) {
		el.setStyles({
			position: '',
			top: null,
			left: null,
			right: null,
			bottom: null,
			'z-index': null,
			height: null,
			width: null
		});
		el.getElement('video').setStyles({
			height: null,
			width: null
		});
		$('Content').setStyle('z-index', null);
	}
	
	function createControls(container) {
		var controls = new Element('div', { 'class': 'controls' }),
			that = this;
		
		//create play/pause
		//------------------------
		var playControl = new Element('div', { 'class': 'playPause control play', html: '<span></span>' });
		playControl.addEvent('click', function() {
			if(that.getPaused()) {
				that.play();
			} else {
				that.pause();
			}
		});
		this.addEvent('play', function () {
			playControl.removeClass('play').addClass('pause');
		});
		this.addEvent('pause', function () {
			playControl.removeClass('pause').addClass('play');
		});
		controls.grab(playControl);
		
		//create progress bar
		//------------------------
		var progressControl = new Element('div', { 'class': 'progress control' });
		var progressBox = new Element('div', { 'class': 'progress_box', html: '<span class="load_progress"><span class="play_progress"></span></span>' });
		progressBox.addEvent('click', function(e) {
			var percent  = Math.max(0, Math.min(1, (e.page.x - progressBox.getPosition().x) / progressBox.getWidth()));
			that.setCurrentTime(percent * that.getDuration());
		});
		var playProgressBar = progressBox.getElement('.play_progress');
		this.addEvent('timeupdate', function() {
			playProgressBar.setStyle('width', (that.getCurrentTime() / that.getDuration()) * (progressBox.getWidth() - 2));
		});
		
		progressControl.grab(progressBox);
		
		var playTime = new Element('div', { 'class': 'play_time', html: '<span class="current_time_display">00:00</span><span class="duration_display">00:00</span>' });
		this.addEvent('timeupdate', function() {
			if(playTime)
				playTime.getElements('.current_time_display').set('text', formatTime(that.getCurrentTime()));
		});
		playTime.getElement('.duration_display').set('text', formatTime(this.getDuration()));
		
		progressControl.grab(playTime);
		controls.grab(progressControl);
		
		//create share button
		//------------------------
		var shareControl = new Element('div', { 'class': 'share control', html: '<span class="share_button">Share</span>' });
		shareControl.addEvent('click', function() {
			that.pause();
			Fisker.share();
		});
		controls.grab(shareControl);
		
		//create mute/unmute button
		//------------------------
		var volumeControl = new Element('div', { 'class': 'volume control', html: '<span></span>' });
		controls.grab(volumeControl);
		
		//create fullscreen button
		//------------------------
		var fullscreenControl = new Element('div', { 'class': 'full_screen control', html: '<span><table border="0" cellpadding="0" cellspacing="0"><tr><td><div class="fs_top_left fs-corner"></div></td><td><div class="fs_top_right fs-corner"></div></td></tr><tr><td><div class="fs_bottom_left fs-corner"></div></td><td><div class="fs_bottom_right fs-corner"></div></td></tr></table></span>' });
		var isFullscreen = false;
		fullscreenControl.addEvent('click', function() {
			if(isFullscreen) {
				fullScreenOff(container);
			} else {

				fullScreenOn(container);
			}
			isFullscreen = !isFullscreen;
		});
		
		controls.grab(fullscreenControl);
		
		return controls;
	}
	
	
	//public api
	return {
		
		Implements: [Events, Options],
		
		options: {
			controls: 'controls',
			height: 250,
			width: 500,
			hasAudio: true
		},
		
		eventQueue: [],
		
		initialize: function(src, options) {
			this.setOptions(options);
			
			this.src = src;
			var _id = this._swfID = videoID(),
				hasAudio = this.options.hasAudio,
				hasControls = this.options.controls,
				that = this;
			
			if(hasControls)
			{
				this.options.reallyHasControls = hasControls;
			}
			delete this.options.hasAudio;
			if(hasControls && !Fisker.iPad) {
				delete this.options.controls;
			}
			this.element = this.video = videoFactory(src, this.options, this._swfID);
			this.element.video = this;
			Video._instances[_id] = this;
			this.flashEventManager = new Events();
			
			if(hasControls && isVideo(this.video) && !Fisker.iPad) {
				this.element = new Element('div', { 'class': 'video-holder' });
				this.element.grab(this.video);
				if(this.getDuration()) {
					this.element.grab(createControls.call(this, this.element));
				} else {
					this.addEvent('loadedmetadata', function() {
						that.element.grab(createControls.call(that, that.element));
						this.removeEvent('loadedmetadata', arguments.callee);
					});
				}
				
			}
			
			
			if(hasAudio) {
				this.addEvent('play', function() {
					Fisker.toggleMusic(false);
				});
				this.addEvent('pause', function() {
					Fisker.toggleMusic(true);
				});
				this.addEvent('ended', function() {
					Fisker.toggleMusic(true);
				});
			}
		},
		
		load: function () {
			if (isVideo(this.video))
			{
				this.video.load();
			}
		},
		
		isVideo: function () {
			return isVideo(this.video);
		},
		
		play: function() {
			
			if (isVideo(this.video))
			{
				if(Fisker.iPad)
				{
					
					var video = this.video;
					function c () { video.play(); } 
					document.body.addEvent('click', c);
					setTimeout(function () {
						var evt = document.createEvent('MouseEvents');
						evt.initMouseEvent('click', true, true, window, 1, 20, 20, false, false, false, false, 0, null);
						document.body.dispatchEvent(evt);
						document.body.removeEvent('click', c);
					}, 1000);
				}
				this.video.play();
			}
			else
			{
				callExternalInterface.call(this, this.video, 'playVid');
			}
		},
		
		pause: function() {
			var e;
			
			if (isVideo(this.video))
			{
				this.video.pause();
			}
			else
			{
				callExternalInterface.call(this, this.video, 'pauseVid');
			}
		},
		
		getVideoWidth: function() {
			return getVideoWidth(this.video);
		},
		
		getVideoHeight: function() {
			return getVideoHeight(this.video);
		},
		
		getCurrentTime: function() {
			return getCurrentTime(this.video);
		},
		
		setCurrentTime: function(time) {
			setCurrentTime(this.video, time);
		},
		
		getDuration: function() {
			return getDuration(this.video);
		},
		
		getPaused: function() {
			return getPaused(this.video);
		},
		
		addEvent: function() {
			addEvent.apply(this, arguments)
		},
		
		removeEvent: function() {
			removeEvent.apply(this, arguments);
		},
		
		fireEvent: function() {
			fireEvent.apply(this, arguments);
		},
		
		toElement: function() {
			return this.element;
		},
		
		setProperty: function (name, value) {
			var problem;
			try
			{
				this.video.setProperty(name, value);
			}
			catch(problem) {}
		},
		
		removeProperty: function (name) {
			var problem;
			try
			{
				this.video.removeProperty(name);
			}
			catch(problem) {}
		},
		
		fade: function (something)
		{
			switch(something)
			{
				case 'hide':
				case 'out':
					Element.setStyle(this.element, 'display', 'none');
					break;
					
				case 'in':
				case 'show':
					Element.setStyle(this.element, 'display', 'block');
					break;
			}
		},
		
		dispose: function ()
		{
			if(!isVideo(this.video))
			{
				this.video.cleanup();
			}
			Element.dispose(this.video);
			this.video = null;
		}
		
	};
	
})());

Video._instances = {};
Video.fireSWFEvent = function(swfID, eventName, eventObj) {
	//console.log('Got SWF event ', eventName, 'from', swfID);
	if (eventObj)
	{
		eventObj.stop = function() { };
	}
	Video._instances[swfID].fireEvent(eventName, eventObj);
};
Video.eiSetup = function(swfId)
{
	//console.log('ExternalInterface is loaded', swfId);
	var IE = 'dumb' + 5 + 100 + Math.pow(2, 100);
	var inst = Video._instances[swfId], f;
	while(inst && inst.eventQueue.length)
	{
		f = inst.eventQueue.pop();
		f();
	}
};

Video.supportsHTML5 = function ()
{
	return (!!document.createElement('video').canPlayType  && !Browser.Engine.presto);
};



Video.popup = function(src, vidOptions, overlayOptions, container) {
	var video = new Video(src, vidOptions),
		el = new Element('div', { 'class': 'video-overlay' }),
		closeBtn = new Element('span', { 'class': 'close-button', text: 'CLOSE X' });
		
	el.grab(closeBtn).grab(video);
	
	var overlay = new Overlay(el, overlayOptions);
	if(container)
	{
		$(container).grab(overlay);
	}
	else
	{
		document.body.grab(overlay);
	}
	
	
	
	video.addEvent('ended', function() {
		overlay.hide();
		$(overlay).destroy();
	});
	
	closeBtn.addEvent('click', function() {
		video.pause();
		overlay.hide();
		$(overlay).destroy();
	});
	overlay.show();
	return overlay;
};


['loadstart', 'progress', 'suspend', 'abort',
	'error', 'emptied', 'stalled', 'play', 'pause',
	'loadedmetadata', 'loadeddata', 'waiting', 'playing',
	'canplay', 'canplaythrough', 'seeking', 'seeked',
	'timeupdate', 'ended', 'ratechange', 'durationchange', 'volumechange'].forEach(function(ev) {
	Element.NativeEvents[ev] = 2;
});
