Ext.namespace('Ext.ux');

/**
 * @class Ext.ux.FileUploader
 * @author David Irving
 * @date 05/30/07
 **/

Ext.ux.FileUploader = function(config) {
		
	this._pollURL = "";
	this._storageURL = "";
	this._myID = Ext.id();
	this._files = new Array();
	this._dialog = null;
	this._store = null;
	
	this.events = {
		startUpload: true,
		uploadFinished: true,
		uploadCancelled: true,
		uploadError: true,
		allUploadsFinished: true
	};
	
	if (!config) { throw('no configuration was passed to fileUploader'); }
	if (!config.storageURL) { throw('storageURL configuration option must be set for fileUploader'); }
	if (!config.pollURL) { throw('pollURL configuration option must be set for fileUploader'); }
	
	this._pollURL = config.pollURL;
	this._storageURL = config.storageURL;
	
}

Ext.extend(Ext.ux.FileUploader,Ext.util.Observable,{
	
	addFile: function(fileField, internalID) {
			for (var i=0;i<this._files.length;i++) {
				if (this._files[i].internalID == internalID) {
					return false;
				}
			}
			this._myID = Ext.id();
			if (navigator.appName == 'Netscape' && navigator.userAgent.indexOf("AppleWebKit") == -1) {
				// Do this slickly because we're using FF
				this._files[this._files.length] = { 
					fileField: fileField,
					internalID: internalID,
					externalID: 0,
					percentComplete: 0,
					status: 'waiting',
					id: this._myID
				};
			} else {
				// Crap.. Safari or IE... Let's kludge this together
				// Add the file as normal
				var i = this._files.length;
				this._files[i] = { 
					fileField: fileField,
					internalID: internalID,
					externalID: 0,
					percentComplete: 0,
					status: 'waiting',
					id: this._myID
				};
				// Create the iframe wrapper & the real field
				var responseArea = document.createElement('div');
				responseArea.id = 'formResponse' + this._files[i].id;
				responseArea.name = 'formResponse' + this._files[i].id;
				responseArea.style.visibility = 'hidden';
				responseArea.style.position = 'absolute';
				responseArea.style.top = '0px';
				//Ext.DomHelper.append(document.body,responseArea);
				document.body.appendChild(responseArea);
				
				
				var holder = document.createElement('div');
				holder.id = 'divWrapper' + this._myID;
				holder.style.visibility = 'hidden';
				holder.style.position = 'absolute';
				holder.style.top = '0px';
				var iframe = document.createElement('iframe');
				iframe.id = 'iframe'+this._myID;	
				if (navigator.userAgent.indexOf("AppleWebKit") == -1) {
					iframe.attachEvent('onload',new Function("document.getElementById('formResponse"+this._myID+"').innerHTML = frames['iframe"+this._myID+"'].document.body.innerHTML;"));
				}
				else {	
					iframe.onload = new Function("document.getElementById('formResponse"+this._myID+"').innerHTML = frames['iframe"+this._myID+"'].document.body.innerHTML;");		
				}
				holder.appendChild(iframe);
				document.body.appendChild(holder);
				
				var iframeContent = '<form name="subform" enctype="multipart/form-data" id="subform" method="POST" action="'+this._storageURL+'"><input type="hidden" name="APC_UPLOAD_PROGRESS" value="'+this._myID+'"><input type=file id="' + this._myID + '" name="' + this._myID + '"></form>';
				if (navigator.userAgent.indexOf("AppleWebKit") == -1) {
					// IE
					var what = this;
					var wi = i;
					var id = this._myID;
					setTimeout(function(){ what.populateIframe(id,wi); },500);
					return;
				} else {
					// Safari
					Ext.DomHelper.insertHtml('beforeEnd',frames['iframe'+this._myID].document.body,iframeContent);
				}
				
				// Hack out the original file element and replace it with some fake stuff
				var fakeFileHolder = document.createElement('div');
				var fakeFilename = document.createElement('input');
				fakeFilename.type = 'text';
				fakeFilename.disabled = true;
				fakeFilename.value = 'No file selected';
				fakeFilename.style.width = '150px';
				fakeFilename.id = 'fakeFilename' + this._myID;
				fakeFileHolder.appendChild(fakeFilename);
				var fakeBrowseButton = document.createElement('input');
				fakeBrowseButton.type = 'button';
				fakeBrowseButton.value = 'Browse...';
				fakeBrowseButton.name = this._myID;
				var what = this;
				fakeBrowseButton.onclick = function () {
					var obj = frames['iframe'+this.name].document.getElementById(this.name);
					var id = this.name;
					obj.onchange = function () {
						document.getElementById('fakeFilename' + id).value = this.value;
					}
					obj.click();
				}
				fakeFileHolder.appendChild(fakeBrowseButton);
				document.getElementById(this._files[i].internalID).parentNode.replaceChild(fakeFileHolder,document.getElementById(this._files[i].internalID));
				this._files[i].fileField = frames['iframe'+this._myID].document.getElementById(this._myID);
			}
			return true;
	},
	
	/**
	 * The below function is ONLY used by IE. I couldn't get it to work the way that Safari works due to the
	 * fact that IE has a 100-400 ms delay between creating the iframe and the iframe actually becoming useable
	 **/
	populateIframe: function(id,i) {
		var iframeContent = '<form name="subform" enctype="multipart/form-data" id="subform" method="POST" action="'+this._storageURL+'"><input type="hidden" name="APC_UPLOAD_PROGRESS" value="'+id+'"><input type=file id="' + id + '" name="' + id + '"></form>';
		frames['iframe'+id].document.body.innerHTML = iframeContent;

		// Hack out the original file element and replace it with some fake stuff
		var fakeFileHolder = document.createElement('div');
		var fakeFilename = document.createElement('input');
		fakeFilename.type = 'text';
		fakeFilename.disabled = true;
		fakeFilename.value = 'No file selected';
		fakeFilename.style.width = '150px';
		fakeFilename.id = 'fakeFilename' + id;
		fakeFileHolder.appendChild(fakeFilename);
		var fakeBrowseButton = document.createElement('input');
		fakeBrowseButton.type = 'button';
		fakeBrowseButton.value = 'Browse...';
		fakeBrowseButton.name = id;
		var what = id;
		fakeBrowseButton.onclick = function () {
			var objT = frames['iframe'+what].document.getElementById(what);
			objT.onchange = function () {
				document.getElementById('fakeFilename' + id).value = objT.value;
			}
			objT.click();
		}
		fakeFileHolder.appendChild(fakeBrowseButton);
		document.getElementById(this._files[i].internalID).parentNode.replaceChild(fakeFileHolder,document.getElementById(this._files[i].internalID));
		this._files[i].fileField = frames['iframe'+id].document.getElementById(id);		
	},
	
	getID: function(internalID) {
		for (var i=0;i<this._files.length;i++) {
			if (this._files[i].internalID == internalID) {
				return this._files[i].externalID;
			}
		}		
		return 0;
	},
	
	upload: function() {
		// Double check to make sure that we actually have a file to upload
		var continueUpload = false;
		for (var i=0;i<this._files.length;i++) {
			if (this._files[i].fileField.value != '') {
				continueUpload = true;
			}
		}
		if (!continueUpload) {
			this.fireEvent('allUploadsFinished');
			return;
		}
		// Render the status display here
		var ids = '';
		if (!this._dialog) {
			if (this._files.length == 1) {
				var height = 100;
			} else {
				var fileCount = 0;
				for (var i=0;i<this._files.length;i++) {
					if (this._files[i].fileField.value) {
						fileCount++;
					}
				}
				if (fileCount == 1) {
					var height = 100;
				} else {
					var height = fileCount * 70;
				}
			}
			var html = '';
			for (var i=0;i<this._files.length;i++) {
				if (this._files[i].fileField.value != '') {
					if (this._files[i].fileField.value.indexOf('/') > -1) {
						var fileParts =  this._files[i].fileField.value.split('/');
					} else {
						var fileParts =  this._files[i].fileField.value.split('\\');
					}
					ids = ids + this._files[i].id + ',';
					var filename = fileParts[fileParts.length-1];
					if (i > 0) {
						var topPadding = "10px";
					} else {
						var topPadding = "0px";
					}
					html = html + '<div style="padding-top:'+topPadding+';padding-bottom:5px;"><div style="float:left">' + filename + '</div><div id="percent'+this._files[i].id+'" style="float:right;font-weight:bold">0% Completed</div></div><br />';
					html = html + '<div style="width:475px;height:15px;background-color:#CCCCCC"><div style="width:0%;height:15px;background:url(\'/images/progressBar.gif\')" id="statusbar'+this._files[i].id+'">&nbsp</div></div>';
				}
			}
			this._dialog = new Ext.Window({
				width: 500,
				height: 100,
				title: 'Uploading Files...',
				html: html,
				modal: true,
				closable: false,
				collapsible: false,
				draggable: false,
				resizable: false
			});
			this._dialog.show();
		}
		
		ids = ids.substr(0,ids.length-1);
		
		for (var i=0;i<this._files.length;i++) {
			if (this._files[i].fileField.value != '') {
				if (navigator.appName == 'Netscape' && navigator.userAgent.indexOf("AppleWebKit") == -1) {
					var formArea = document.createElement('div');
					formArea.id = 'formHolder' + this._files[i].id;
					formArea.style.visibility = 'hidden';
					Ext.DomHelper.append(document.body,formArea);
					var responseArea = document.createElement('div');
					responseArea.id = 'formResponse' + this._files[i].id;
					responseArea.name = 'formResponse' + this._files[i].id;
					responseArea.style.visibility = 'hidden';
					Ext.DomHelper.append(document.body,responseArea);
					var fileSubmitForm = Ext.DomHelper.append('formHolder' + this._files[i].id,{
						tag: 'form',
						name: 'submissionForm' + this._files[i].id,
						id: 'submissionForm' + this._files[i].id,
						action: this._storageURL,
						enctype: 'multipart/form-data'
					}, true);
			
					Ext.DomHelper.append('submissionForm' + this._files[i].id,{
						tag: 'input',
						name: 'APC_UPLOAD_PROGRESS',
						type: 'hidden',
						value: this._files[i].id
					});
			
					var fid = this._files[i].fileField.id;
					var id = this._files[i].id;
					var fileElem = document.getElementById(fid).cloneNode(true);
					
					fileSubmitForm.appendChild(fileElem);
					var flyweight = Ext.fly(Ext.get('formResponse'+id),'fly'+id);
					flyweight.getUpdateManager().formUpdate(fileSubmitForm.dom);
				} else {
					// Handle IE & Safari
					var form = frames['iframe'+this._files[i].id].document.getElementById('subform');									
					form.submit();
				}
			}			
		}
		var xmlReader = new Ext.data.XmlReader({ record: 'file' }, ['id', 'percent']);
		var proxy = new Ext.data.HttpProxy({ url: this._pollURL + '&ids=' + ids, method: 'get' });
		var purl = this._pollURL;
		proxy.on('beforeload',function(proxy) {
			var date = new Date();
			var ts = date.getTime();
			proxy.conn.url = purl + '&ids=' + ids + '&cache=' + ts;
		});
		this._store = new Ext.data.Store({
			proxy: proxy,
			reader: xmlReader
		});
		this._store.on('load',function() {
			var allComplete = true;
			for (var i=0;i<this._store.getCount();i++) {			
				var rec = this._store.getAt(i);
				if (rec.get('percent') < 100) {
					Ext.get('percent'+rec.get('id')).dom.innerHTML = rec.get('percent')+'% Completed';
					document.getElementById('statusbar'+rec.get('id')).style.width = rec.get('percent')+'%';
					allComplete = false;
				}
			}
			if (!allComplete) {
				var what = this;
				setTimeout(function() {
					what._store.reload();
				},500);
			} else {
				this._dialog.hide();
				// Reset everything
				this._dialog = null;
				if (Ext.get('uploadStatus')) {
					Ext.get('uploadStatus').remove();
				}
				for (var i=0;i<this._files.length;i++) {
					this._files[i].status = 'waiting';
					this._files[i].externalID = 0;
					this._files[i].percentComplete = 0;
					if (Ext.get('formResponse' + this._files[i].id)) {
						Ext.get('formResponse' + this._files[i].id).dom.innerHTML = '--NULL--';
					}
					if (navigator.appName != 'Netscape' || navigator.userAgent.indexOf("AppleWebKit") != -1) {
						// Have to reset Safari & IE fileFields
						var iframeContent = '<form name="subform" enctype="multipart/form-data" id="subform" method="POST" action="'+this._storageURL+'"><input type="hidden" name="APC_UPLOAD_PROGRESS" value="'+this._files[i].id+'"><input type=file id="' + this._files[i].id + '" name="' + this._files[i].id + '"></form>';
						if (navigator.userAgent.indexOf("AppleWebKit") == -1) {
							// IE
							frames['iframe'+this._files[i].id].document.body.innerHTML = iframeContent;
						} else {
							// Safari
							Ext.DomHelper.insertHtml('beforeEnd',frames['iframe'+this._files[i].id].document.body,iframeContent);
						}
						this._files[i].fileField = frames['iframe'+this._files[i].id].document.getElementById(this._files[i].id);
						//document.getElementById('fakeFilename' + this._files[i].id).value = 'No file selected';
					}
				}
				this.fireEvent('allUploadsFinished');
			}
		},this);
		this._store.load();	
	}
});

