define("dojox/form/uploader/plugins/Flash", [
	"dojo/dom-form",
	"dojo/dom-style",
	"dojo/dom-construct",
	"dojo/dom-attr",
	"dojo/_base/declare",
	"dojo/_base/config",
	"dojo/_base/connect",
	"dojo/_base/lang",
	"dojo/_base/array",
	"dojox/form/uploader/plugins/HTML5",
	"dojox/embed/Flash"
],function(domForm, domStyle, domConstruct, domAttr, declare, config, connect, lang, array, formUploaderPluginsHTML5, embedFlash){


var pluginsFlash = declare("dojox.form.uploader.plugins.Flash", [], {
	// summary:
	//		A plugin for dojox.form.Uploader that utilizes a Flash SWF for handling to upload in IE.
	//		All other browsers will use the HTML5 plugin, unless force="flash" is used, then Flash
	//		will be used in all browsers. force="flash"	is provided because Flash has some features
	//		that HTML5 does not yet have. But it is still not recommended because of the many problems
	//		that Firefox and Webkit have with the Flash plugin.
	//
	// description:
	//		Inherits all properties from dojox.form.Uploader and formUploaderPluginsHTML5.
	//		All properties and methods listed here are specific to the Flash plugin only.
	//
	//		Version: 1.6

	
	// swfPath:String
	//		Path to SWF. Can be overwritten or provided in djConfig.
	swfPath:config.uploaderPath || require.toUrl("dojox/form/resources/uploader.swf"),

	// skipServerCheck: Boolean
	//		If true, will not verify that the server was sent the correct format.
	//		This can be safely set to true. The purpose of the server side check
	//		is mainly to show the dev if they've implemented the different returns
	//		correctly.
	skipServerCheck:true,

	// serverTimeout:Number (milliseconds)
	//		The amount of time given to the uploaded file
	//		to wait for a server response. After this amount
	//		of time, the onComplete is fired but with a 'server timeout'
	//		error in the returned item.
	serverTimeout: 2000,

	// isDebug: Boolean
	//		If true, outputs traces from the SWF to console. What exactly gets passed
	//		is very relative, and depends upon what traces have been left in the DEFT SWF.
	isDebug:false,

	// devMode: Boolean.
	//		Re-implemented. devMode increases the logging, adding style tracing from the SWF.
	devMode:false,

	// deferredUploading: Number (1 - X)
	//		(Flash only) throttles the upload to a certain amount of files at a time.
	//		By default, Flash uploads file one at a time to the server, but in parallel.
	//		Firefox will try to queue all files at once, leading to problems. Set this
	//		to the amount to upload in parallel at a time.
	//		Generally, 1 should work fine, but you can experiment with queuing more than
	//		one at a time.
	//		This is of course ignored if selectMultipleFiles equals false.
	deferredUploading:0,

	// force: String
	//		Use "flash" to always use Flash (and hopefully force the user to download the plugin
	//		if they don't have it).
	force:"",

	postMixInProperties: function(){
		if(!this.supports("multiple")){
			// Flash will only be used in IE6-8 unless force="flash"
			this.uploadType = "flash";
			this._files = [];
			this._fileMap = {};
			this._createInput = this._createFlashUploader;
			this.getFileList = this.getFlashFileList;
			this.reset = this.flashReset;
			this.upload = this.uploadFlash;
			this.fieldname = "flashUploadFiles"; ///////////////////// this.name
		}
		this.inherited(arguments);
	},

	/*************************
	 *	   Public Events	 *
	 *************************/

	onReady: function(/*dojox/form/FileUploader*/ uploader){
		// summary:
		//		Stub - Fired when embedFlash has created the
		//		Flash object, but it has not necessarilly finished
		//		downloading, and is ready to be communicated with.
	},

	onLoad: function(/*dojox/form/FileUploader*/ uploader){
		// summary:
		//		Stub - SWF has been downloaded 100%.
	},

	onFileChange: function(fileArray){
		// summary:
		//		Stub - Flash-specific event. Fires on each selection of files
		//		and only provides the files selected on that event - not all files
		//		selected, as with HTML5
	},

	onFileProgress: function(fileArray){
		// summary:
		//		Stub - Flash-specific event. Fires on progress of upload
		//		and only provides a file-specific event
	},


	/*************************
	 *	   Public Methods	 *
	 *************************/

	getFlashFileList: function(){
		// summary:
		//		Returns list of currently selected files
		return this._files; // Array
	},

	flashReset: function(){
		this.flashMovie.reset();
		this._files = [];
	},

	/*************************
	 *	   Private Methods	 *
	 *************************/

	uploadFlash: function(/*Object ? */ formData){
		// summary:
		//		Uploads selected files. Alias "upload()" should be used instead.
		// tags:
		//		private
		this.onBegin(this.getFileList());
		formData.returnType = "F";
		this.flashMovie.doUpload(formData);
	},

	_change: function(fileArray){
		this._files = this._files.concat(fileArray);
		array.forEach(fileArray, function(f){
			f.bytesLoaded = 0;
			f.bytesTotal = f.size;
			this._fileMap[f.name+"_"+f.size] = f;
		}, this);
		this.onChange(this._files);
		this.onFileChange(fileArray);
	},
	_complete: function(fileArray){
		var o = this._getCustomEvent();
		o.type = "load";
		this.onComplete(fileArray);
	},
	_progress: function(f){
		this._fileMap[f.name+"_"+f.bytesTotal].bytesLoaded = f.bytesLoaded;
		var o = this._getCustomEvent();
		this.onFileProgress(f);
		this.onProgress(o);
	},
	_error: function(err){
		this.onError(err);
	},
	_onFlashBlur: function(fileArray){
		//console.log("UploaderFlash._onFlashBlur");
	},

	_getCustomEvent: function(){
		var o = {
			bytesLoaded:0,
			bytesTotal:0,
			type:"progress",
			timeStamp:new Date().getTime()
		};


		for(var nm in this._fileMap){
			o.bytesTotal += this._fileMap[nm].bytesTotal;
			o.bytesLoaded += this._fileMap[nm].bytesLoaded;
		}
		o.decimal = o.bytesLoaded / o.bytesTotal;
		o.percent = Math.ceil((o.bytesLoaded / o.bytesTotal)*100)+"%";
		return o; // Object
	},

	_connectFlash: function(){
		// summary:
		//		Subscribing to published topics coming from the
		//		Flash uploader.

		// Sacrificing some readability for compactness. this.id
		// will be on the beginning of the topic, so more than
		// one uploader can be on a page and can have unique calls.

		this._subs = [];
		this._cons = [];

		var doSub = lang.hitch(this, function(s, funcStr){
			this._subs.push(connect.subscribe(this.id + s, this, funcStr));
		});

		doSub("/filesSelected", "_change");
		doSub("/filesUploaded", "_complete");
		doSub("/filesProgress", "_progress");
		doSub("/filesError", "_error");
		doSub("/filesCanceled", "onCancel");
		doSub("/stageBlur", "_onFlashBlur");

		this.connect(this.domNode, "focus", function(){
			// TODO: some kind of indicator that the Flash button is in focus
			this.flashMovie.focus();
			this.flashMovie.doFocus();
		});
		if(this.tabIndex>=0){
			domAttr.set(this.domNode, "tabIndex", this.tabIndex);
		}
	},
	_createFlashUploader: function(){
		// summary:
		//		Internal. Creates Flash Uploader

		var w = this.btnSize.w;
		var h = this.btnSize.h;
		if(!w){
			// FIXME: Commit this
			setTimeout(dojo.hitch(this, function(){
				this._getButtonStyle(this.domNode);
				this._createFlashUploader();
			}), 200);
			return;
		}
		var url = this.getUrl();
		if(url){
			if(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("/")+"/";
				url = loc+url;
			}
		}else{
			console.warn("Warning: no uploadUrl provided.");
		}

		this.inputNode = domConstruct.create("div", {className:"dojoxFlashNode"}, this.domNode, "first");
		domStyle.set(this.inputNode, {
			position:"absolute",
			top:"-2px",
			width:w+"px",
			height:h+"px",
			opacity:0
		});



		var args = {
			expressInstall:true,
			path: (this.swfPath.uri || this.swfPath) + "?cb_" + (new Date().getTime()),
			width: w,
			height: h,
			allowScriptAccess:"always",
			allowNetworking:"all",
			vars: {
				uploadDataFieldName: this.flashFieldName || this.name+"Flash",
				uploadUrl: url,
				uploadOnSelect: this.uploadOnSelect,
				deferredUploading:this.deferredUploading || 0,
				selectMultipleFiles: this.multiple,
				id: this.id,
				isDebug: this.isDebug,
				noReturnCheck: this.skipServerCheck,
				serverTimeout:this.serverTimeout
			},
			params: {
				scale:"noscale",
				wmode:"transparent",
				wmode:"opaque",
				allowScriptAccess:"always",
				allowNetworking:"all"
			}

		};

		this.flashObject = new embedFlash(args, this.inputNode);
		this.flashObject.onError = lang.hitch(function(msg){
			console.error("Flash Error: " + msg);
		});
		this.flashObject.onReady = lang.hitch(this, function(){
			this.onReady(this);
		});
		this.flashObject.onLoad = lang.hitch(this, function(mov){
			this.flashMovie = mov;
			this.flashReady = true;

			this.onLoad(this);
		});
		this._connectFlash();
	}
});
dojox.form.addUploaderPlugin(pluginsFlash);


return pluginsFlash;
});
