/*
	Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
	Available via Academic Free License >= 2.1 OR the modified BSD license.
	see: http://dojotoolkit.org/license for details
*/


if(!dojo._hasResource["dojox.av._Media"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojox.av._Media"] = true;
dojo.provide("dojox.av._Media");

dojo.declare("dojox.av._Media", null, {
	// summary:
	//		Used as a mixin for dojox and AIR media
	//	description:
	//		Calculates the current status of the playing media and fires
	//		the appropriate events.
	//
	mediaUrl:"",
	//
	// initialVolume: Float?
	//		The initial volume setting of the player. Acccepts between 0 and 1.
	initialVolume:1,
	//
	//  autoPlay:Boolean?
	//		Whether the video automatically plays on load or not.
	autoPlay: false,
	//
	//	bufferTime: Number?
	//		Time in milliseconds that the video should be loaded before it will
	//		play. May pause and resume to build up buffer. Prevents stuttering.
	//	Note:
	//		Older FLVs, without a duration, cannot be buffered.
	bufferTime: 2000,
	//
	//	minBufferTime: Number
	//		Time in milliseconds bwteen the playhead time and loaded time that
	//		will trigger the buffer. When buffer is triggered, video will pause
	//		until the bufferTime amount is buffered.
	//		Note: Should be a small number, greater than zero.
	minBufferTime:300,
	//
	// updateTime: Number
	//		How often, in milliseconds to get an update of the video position.
	updateTime: 100,
	//
	//  id: String?
	//		The id of this widget and the id of the SWF movie.
	id:"",
	//
	// isDebug: Boolean?
	//		Setting to true tells the SWF to output log messages to Firebug.
	isDebug: false,
	//
	// percentDownloaded: read-only-Number
	//		The percentage the media has downloaded; from 0-100
	percentDownloaded:0,
	//
	// _flashObject: read-only-Object
	//	The dojox.embed object
	_flashObject:null,
	//
	// flashMedia: read-only-SWF
	//		The SWF object. Methods are passed to this.
	flashMedia:null,
	//
	// allowScriptAccess: String
	//		Whether the SWF can access the container JS
	allowScriptAccess:"always",
	//
	// allowNetworking: String
	//		Whether SWF is restricted to a domain
	allowNetworking: "all",
	//
	//	wmode: String
	//		The render type of the SWF
	wmode: "transparent",
	//
	//	allowFullScreen: Boolean
	//		Whether to allow the SWF to go to fullscreen
	allowFullScreen:true,

	_initStatus: function(){
		// summary:
		//		Connect mediaStatus to the media.
		//
		this.status = "ready";
		this._positionHandle = dojo.connect(this, "onPosition", this, "_figureStatus");

	},

	//  ==============  //
	//  Player Getters  //
	//  ==============  //

	getTime: function(){
		// summary:
		// 		Returns the current time of the video
		//	Note:
		//		Consider the onPosition event, which returns
		//		the time at a set interval. Too many trips to
		//		the SWF could impact performance.
		return this.flashMedia.getTime(); // Float
	},

	//  =============  //
	//  Player Events  //
	//  =============  //

	onLoad: function(/* SWF */ mov){
		// summary:
		// 		Fired when the SWF player has loaded
		// 		NOT when the video has loaded
		//
	},

	onDownloaded: function(/* Number */percent){
		// summary:
		//		Fires the amount of that the media has been
		//		downloaded. Number, 0-100
	},

	onClick: function(/* Object */ evt){
		// summary:
		// 		TODO: Return x/y of click
		// 		Fires when the player is clicked
		// 		Could be used to toggle play/pause, or
		// 		do an external activity, like opening a new
		//		window.
	},

	onSwfSized: function(/* Object */ data){
		// summary:
		// 		Fired on SWF resize, or when its
		// 		toggled between fullscreen.
	},

	onMetaData: function(/* Object */ data, /* Object */ evt){
		// summary:
		// 		The video properties. Width, height, duration, etc.
		// 		NOTE: 	if data is empty, this is an older FLV with no meta data.
		// 				Duration cannot be determined. In original FLVs, duration
		//				could only be obtained with Flash Media Server.
		// 		NOTE: 	Older FLVs can still return width and height
		//				and will do so on a second event call
		this.duration = data.duration;
	},

	onPosition: function(/* Float */ time){
		// summary:
		//		The position of the playhead in seconds
	},

	onStart: function(/* Object */ data){
		// summary:
		// 		Fires when video starts
		// 		Good for setting the play button to pause
		// 		during an autoPlay for example
	},

	onPlay: function(/* Object */ data){
		// summary:
		// 		Fires when video starts and resumes
	},

	onPause: function(/* Object */ data){
		// summary:
		// 		Fires when the pause button is clicked
	},

	onEnd: function(/* Object */ data){
		// summary:
		// 		Fires when video ends
		// 		Could be used to change pause button to play
		// 		or show a post video graphic, like YouTube
	},

	onStop: function(){
		// summary:
		// Fire when the Stop button is clicked
		// TODO: 	This is not hooked up yet and shouldn't
		//			fire.
	},

	onBuffer: function(/* Boolean */ isBuffering){
		// summary:
		//		Fires a boolean to tell if media
		//		is paused for buffering or if buffering
		//		has finished
		this.isBuffering = isBuffering;
	},

	onError: function(/* Object */ data, /* String */ url){
		// summary:
		// 		Fired when the player encounters an error
		// example:
		//		| console.warn("ERROR-"+data.type.toUpperCase()+":",
		//		|		data.info.code, " - URL:", url);
		console.warn("ERROR-"+data.type.toUpperCase()+":", data.info.code, " - URL:", url);
	},

	onStatus: function(/* Object */data){
		// summary:
		// 		Simple status
	},

	onPlayerStatus: function(/* Object */data){
		// summary:
		// 		The status of the video from the SWF
		// 		playing, stopped, bufering, etc.
	},

	onResize: function(){

	},

	_figureStatus: function(){
		// summary:
		//		Calculate media status, based on playhead movement, and
		//		onStop and onStart events
		// TODO:
		//		Figure in real status from the media for more accurate results.
		//
		var pos = this.getTime();
		//console.log(pos, this.duration,  (pos>this.duration-.5), (this.duration && pos>this.duration-.5))

		if(this.status=="stopping"){
			// stop was fired, need to fake pos==0
			this.status = "stopped";
			this.onStop(this._eventFactory());

		}else if(this.status=="ending" && pos==this._prevPos){
			this.status = "ended";
			this.onEnd(this._eventFactory());

		}else if(this.duration && pos>this.duration-.5){
			this.status="ending"

		}else if(pos===0 ){//|| this.status == "stopped"
			if(this.status == "ready"){
				//never played
			}else{
				//stopped
				this.status = "stopped";
				if(this._prevStatus != "stopped"){
					this.onStop(this._eventFactory());
				}
			}

		}else{
			// pos > 0
			if(this.status == "ready"){
				//started
				this.status = "started";
				this.onStart(this._eventFactory());
				this.onPlay(this._eventFactory());

			}else if(this.isBuffering){
				this.status = "buffering";

			}else if(this.status == "started" || (this.status == "playing" &&  pos != this._prevPos)){
				this.status = "playing";
				//this.onPosition(this._eventFactory());

			}else if(!this.isStopped && this.status == "playing" && pos == this._prevPos){
				this.status = "paused";
				console.warn("pause", pos, this._prevPos)
				if(this.status != this._prevStatus){
					this.onPause(this._eventFactory());
				}

			}else if((this.status == "paused" ||this.status == "stopped") && pos != this._prevPos){
				this.status = "started";
				this.onPlay(this._eventFactory());
			}
		}

		this._prevPos = pos;
		this._prevStatus = this.status;
		this.onStatus(this.status);


	},

	_eventFactory: function(){
		// summary:
		//		Creates a generic event object.
		//
		var evt = {
			//position:this._channel.position,
			//seconds:this.toSeconds(this._channel.position*.001),
			//percentPlayed:this._getPercent(),
			status:this.status
		}
		return evt; // Object
	},



	_sub: function(topic, method){
		// summary:
		// helper for subscribing to topics
		dojo.subscribe(this.id+"/"+topic, this, method);
	},

	_normalizeVolume: function(vol){
		// summary:
		//		Ensures volume is less than one
		//
		if(vol>1){
			while(vol>1){
				vol*=.1
			}
		}
		return vol;
	},

	_normalizeUrl: function(_url){
		// summary:
		//		Checks that path is relative to HTML file or
		//		convertes it to an absolute path.
		//

		console.log("  url:", _url);

		if(_url && (_url.toLowerCase().indexOf("http")<0 || _url.indexOf("/") == 0)){
			//
			// Appears to be a relative path. Attempt to  convert it to absolute,
			// so it will better target the SWF.
			var loc = window.location.href.split("/");
			loc.pop();

			loc = loc.join("/")+"/";
			console.log("  loc:", loc);
			_url = loc+_url;
		}
		return _url;
	},

	destroy: function(){
		// summary:
		// 		destroys flash
		if(!this.flashMedia){
			this._cons.push(dojo.connect(this, "onLoad", this, "destroy"));
			return;
		}
		dojo.forEach(this._subs, function(s){
			dojo.unsubscribe(s);
		});
		dojo.forEach(this._cons, function(c){
			dojo.disconnect(c);
		});
		this._flashObject.destroy();
		//dojo._destroyElement(this.flashDiv);

	}
});

}
