FileUploadEntry = {};
FileUploadEntry = Class.create();


FileUploadEntry.INITIALIZED = "initialized";
FileUploadEntry.READY = "ready";
FileUploadEntry.UPLOAD_IN_PROGRESS = "progress";

FileUploadEntry.UPLOAD_CANCELED = "canceled";
FileUploadEntry.UPLOAD_SUCCESS = "done";
FileUploadEntry.UPLOAD_TRANSFER_ERROR = "transfer_error";
FileUploadEntry.UPLOAD_SERVER_ERROR = "server_error";
FileUploadEntry.UPLOAD_SIZE_ERROR = "size_error";
FileUploadEntry.UPLOAD_FORBIDDEN = "forbidden";

FileUploadEntry.LABELS = {};
FileUploadEntry.LABELS[FileUploadEntry.INITIALIZED] = '';
FileUploadEntry.LABELS[FileUploadEntry.READY] = '';
FileUploadEntry.LABELS[FileUploadEntry.UPLOAD_IN_PROGRESS] = '';
FileUploadEntry.LABELS[FileUploadEntry.UPLOAD_CANCELED] = '';
FileUploadEntry.LABELS[FileUploadEntry.UPLOAD_FORBIDDEN] = 'Uploading forbidden';

FileUploadEntry.clearControlTemplate = 
   [	
	new E('a',
			{
				'style':'', 
				'onclick': function (context) { return 'var entry = FileUploadEntry.getComponent(this); entry.uploadObject.clear(entry); return false;';}, 
				'className':function (context) { return 'rich-fileupload-anc ' + Richfaces.evalMacro("className", context); },
				'href':'#'
			},
		    [
		     	new T(function (context) {return Richfaces.evalMacro("controlLink", context);} )
		    ])
   ];

FileUploadEntry.stopControlTemplate = 
   [
	new E('a',
			{
				'style':'', 
				'onclick': function (context) { return 'FileUploadEntry.getComponent(this).uploadObject.stop(); return false;';}, 
				'className':function (context) { return 'rich-fileupload-anc ' + Richfaces.evalMacro("className", context); }, 
				'href':'#'
			},
		    [
		     	new T(function (context) {return Richfaces.evalMacro("controlLink", context);} )
		    ])
	];

FileUploadEntry.cancelControlTemplate = 
   [
	new E('a',
			{
				'style':'', 
				'onclick': function (context) { return 'var entry = FileUploadEntry.getComponent(this); entry.uploadObject.clear(entry); return false;';}, 
				'className':function (context) { return 'rich-fileupload-anc ' + Richfaces.evalMacro("className", context); }, 
				'href':'#'
			},
		    [
		     	new T(function (context) {return Richfaces.evalMacro("controlLink", context);} )
		    ])
	];

FileUploadEntry.template = 
	[
	 new E('table', 
			 {'cellspacing':'0', 'cellpadding':'0', 'border':'0', 'style':'width:100%'},
			 [
			  new E('tbody',{},
					  [
					   new E('tr',{},
							   [
							    new E('td',{'className':function (context) { return 'rich-fileupload-font rich-fileupload-name rich-fileupload-table-td ' + Richfaces.evalMacro("className", context);}},
							    		[
							    		 new E('div',{'className':'rich-fileupload-name-padding','style':function (context) {return 'overflow : hidden; width:' + Richfaces.evalMacro("fileEntryWidth", context);}},
							    				 [
							    				  new ET(function (context) { return Richfaces.evalMacro("fileName", context)})
							    				  ]),
							    		 new E('div',{ }),
							    		 new E('div',{'className':'rich-fileupload-name-padding','style':function (context) {return 'overflow : hidden; width:' + Richfaces.evalMacro("fileEntryWidth", context);}},
							    				[
							    				 new ET(function (context) { return Richfaces.evalMacro("label", context)})
							    				 ])
							    		]),
					    		 new E('td',{'style':'vertical-align: center;', 'className':'rich-fileupload-table-td'},
					    				 [
					    				  new E('div',{'className':'rich-fileupload-font rich-fileupload-del'}, 
			    								[
		    								    	//FileUploadEntry.clearControlTemplate
		    								    ])
					    				  ]),
			    				  new E('td',{'className':'rich-fileupload-table-td'},
			    						  [
			    						   new E('div',{'className':'rich-fileupload-font rich-fileupload-scroll'},[ new T ('\u00A0') ])
			    						   ])
							    ])
					   ])
			  ])
	 ];



FileUploadEntry.getComponent = function(elt) {
	while (elt) {
		var component = elt.component;
		if (component) {
			return component
		} else {
			elt = elt.parentNode;
		}
	}
};

Object.extend(FileUploadEntry.prototype, {

	fileInput: null,
	
	uploadObject: null,

	state: FileUploadEntry.INITIALIZED,
	
	initialize: function(fileInput, uploadObject) {
		this.fileInput = fileInput;
		this.uploadObject = uploadObject;
		
		var content = FileUploadEntry.template.invoke('getContent', {fileName: $F(this.fileInput), fileEntryWidth: uploadObject.getFileEntryWidth(), className : this.uploadObject.classes.FILE_ENTRY.ENABLED }).join('');
		
		Element.insert(this.uploadObject.items, content);
	
		this.entryElement = this.uploadObject.items.childNodes[this.uploadObject.items.childNodes.length - 1];
		this.entryElement.component = this;
		this.statusLabel = this.entryElement.rows[0].cells[0].lastChild;
		this.controlArea = this.entryElement.rows[0].cells[1].firstChild;
		this.progressArea = this.entryElement.rows[0].cells[0].childNodes[1];
	},
	
	upload: function() {
		this.setState(FileUploadEntry.UPLOAD_IN_PROGRESS);
		this.setupProgressBar();
		this.uploadObject.submitForm(this);
	},
	
	setupProgressBar: function () {
		this.progressArea.appendChild(this.uploadObject._progressBar);
		this.uploadObject.prepareProgressBar();
	},
	
	setupLabelUpdate: function () {
		this.updateLabel();
		this.labelUpdateInterval = setInterval(function () { this.updateLabel(); }.bind(this), this.uploadObject.progressBar.options['pollinterval']);
	},
	
	updateLabel: function () {
		if (this.state != FileUploadEntry.UPLOAD_IN_PROGRESS) {
			clearInterval(this.labelUpdateInterval);
		}else {
			var p = this.uploadObject.progressBar.getValue();
			if (p) {
				var content = this.uploadObject.labelMarkup.invoke('getContent', this.uploadObject.progressData.getContext(p)).join('');
				this.statusLabel.innerHTML = content;
		
			}
		}
	},
	
	finishProgressBar: function () {
		this.uploadObject.finishProgressBar();
	},
	
	stop: function() {
		this.uploadObject.stopScript(this.uid, this.uploadObject.formId);
	},
	
	_clearInput: function() {
		Richfaces.removeNode(this.fileInput);
		this.fileInput = null;
	},
	
	_clearEntry: function() {
		Richfaces.removeNode(this.entryElement);
		this.entryElement = null;
	},
	
	clear: function() {
		this._clearInput();
		this._clearEntry();
	},

	setState: function(newState) {
		var oldState = this.state;
		this.state = newState;
		
		Element.clearChildren(this.statusLabel);
		Element.clearChildren(this.controlArea);

		Element.insert(this.statusLabel, FileUploadEntry.LABELS[newState]);

		if (newState == FileUploadEntry.UPLOAD_IN_PROGRESS) {
			Element.update(this.controlArea, FileUploadEntry.stopControlTemplate.invoke('getContent',{'controlLink': FileUploadEntry.LABELS['entry_stop'],'className': this.uploadObject.classes.FILE_ENTRY_CONTROL.ENABLED}).join(''));
		} else if (newState == FileUploadEntry.UPLOAD_SUCCESS) {
			Element.update(this.controlArea, FileUploadEntry.clearControlTemplate.invoke('getContent',{'controlLink': FileUploadEntry.LABELS['entry_clear'],'className': this.uploadObject.classes.FILE_ENTRY_CONTROL.ENABLED}).join(''));
		} else {
			Element.update(this.controlArea, FileUploadEntry.cancelControlTemplate.invoke('getContent',{'controlLink': FileUploadEntry.LABELS['entry_cancel'],'className': this.uploadObject.classes.FILE_ENTRY_CONTROL.ENABLED}).join(''));
		}
		
		if (newState == FileUploadEntry.UPLOAD_SUCCESS) {
			this._clearInput();
		}
		
		this.uploadObject.notifyStateChange(this, oldState);
	}
	
});

ProgressData = Class.create();
Object.extend(ProgressData.prototype, {
	size: null,
	
	startTime: null,
	
	initialize: function(size) {
		this.size = size;
		this.startTime = parseInt((new Date().getTime())/1000);
	},
	
	ss: function () {
		return parseInt((this.time - this.startTime) % 60) + "";
	},
	
	mm: function () {
		return parseInt((this.time - this.startTime)/60)+ "";
	},
	
	hh: function () {
		return parseInt((this.time - this.startTime)/3600) + "";
	},
	
	B: function () {
		return this.size;
	},
	
	KB: function () {
		return parseInt(this.size/1024);
	},
	
	MB: function () {
		return parseInt(this.size/(1024*1024));
	},
	
	getContext: function  (p) {
		var context = {};
		this.time = parseInt((new Date().getTime())/1000);
		context['B'] = this.B();
		context['KB'] = this.KB();
		context['MB'] = this.MB();
		context['ss'] = this.ss();
		context['mm'] = this.mm();
		context['hh'] = this.hh();
		var s = this.size;
		this.size = (this.size * p)/100;
		context['_B'] = this.B();
		context['_KB'] = this.KB();
		context['_MB'] = this.MB();
		this.size = s;
		return context;
	}	
	
});

LoadWatcher = Class.create();
Object.extend(LoadWatcher.prototype, {
	initialize: function(iframe, callback, viewStateUpdater) {
		this.iframe = iframe;
		this.callback = callback;
		this.viewStateUpdater = viewStateUpdater;
	
		this.loadObserver = function() {
			if (!this.stopped) {
				this.stop();
				this.onload();
			}
		}.bind(this);

		Event.observe(this.iframe, 'load', this.loadObserver);
		
		this.interval = setInterval(function() {
			if (!this.stopped) {
				var loaded = false;
				var error = null;

				try {
					if (this.iframe.contentWindow && this.iframe.contentWindow.document) {
						loaded = /complete/.test(this.iframe.contentWindow.document.readyState);
					}
				} catch (e) {
					error = e;
				}
				
				if (error) {
					this.stop();
					this.onerror();
				} else if (loaded) {
					this.stop();
					this.onload();
				}
			}
		}.bind(this), 200);
	},
	
	onerror: function() {
		this.callback(FileUploadEntry.UPLOAD_TRANSFER_ERROR);
	},
	
	onload: function() {
		var iframeDocument = this.iframe.contentWindow.document;
		var elt = iframeDocument.getElementById('_richfaces_file_upload_stopped');
		var restr = iframeDocument.getElementById('_richfaces_file_upload_size_restricted');
		var forb = iframeDocument.getElementById('_richfaces_file_upload_forbidden');
		if (elt) {
			this.callback(FileUploadEntry.UPLOAD_CANCELED);
		} else if (restr) {
			this.callback(FileUploadEntry.UPLOAD_SIZE_ERROR);
		} else if (forb) {
			this.callback(FileUploadEntry.UPLOAD_SIZE_ERROR);
		} else {
			var state = iframeDocument.getElementById('javax.faces.ViewState');
			if (state) {
				this.viewStateUpdater(state.value);
			}
			this.callback(FileUploadEntry.UPLOAD_SUCCESS);
		}
	},
	
	stop: function() {
		this.stopped = true;
		
		if (this.loadObserver) {
			Event.stopObserving(this.iframe, 'load', this.loadObserver);
			this.loadObserver = null;
		}
		
		if (this.interval) {
			clearInterval(this.interval);
			this.interval = null;
		}
	}
});


FileUpload = {};
FileUpload = Class.create();

Object.extend(FileUpload.prototype, {
	
	idCounter: 0,
	
	progressBar: null,

	iframe: null,
	
	element: null,
	
	entries: new Array(),
	
	activeEntry: null,
	
	options: null,
	
	runUpload: false,

	classes: null,

	events: null,
	
	maxFileBatchSize: null,
	
	uploadedCount: 0,

	initialize: function(id, formId, stopScript, getFileSizeScript, progressBarId, classes, label, maxFiles, events, disabled, acceptedTypes, options, labels) {
		this.id = id;
		this.element = $(this.id);
		if (formId != '') {
			this.formId = formId;
			this.form = $(formId);
		}else {
			var f = this._getForm();
			this.formId = (f) ? f.id : null;
			this.form = f;
		}
		this._progressBar = $(progressBarId);
		this.progressBar = this._progressBar.component;
		this.entries = new Array(); 
		
		this.labelMarkup = label;
		this.disabled = disabled;
		
		this.element.component = this;
		this.acceptedTypes = acceptedTypes;
		
		this.stopScript = stopScript;
		this.getFileSizeScript = getFileSizeScript;
		
		this.items = $(this.id + ":fileItems");
		this.classes = classes;
		this.events = events;

		this.maxFileBatchSize = maxFiles;
		this.currentInput = $(this.id + ":file");

		this.options = options || {};
		this.initEvents();
		this.setupAutoUpload();
		this.checkFrame();
		//this.initFileEntryWidth();
		this.initLabels(labels);
		this.processButtons();
		this.initFileInput();
	},
	
	initLabels: function (labels) {
		if (labels) {
			for (var l in labels) {
				FileUploadEntry.LABELS[l] = labels[l];
			}
		}
	},
	
	initFileInput: function () {
		var o = this.currentInput;
		var p = o.parentNode.parentNode;
		p = $(p);
		if (p.getWidth() != 0) {
			o.parentNode.style.width = p.getWidth() + "px";
			o.parentNode.style.height = p.getHeight() + "px";
			if (p._onmouseover) {
				p.onmouseover = p._onmouseover;
			}
		}else {
			p._onmouseover = p.onmouseover;
			p.onmouseover = function () {this.initFileInput(); p._onmouseover(); }.bind(this);
		}
	},
	
	getFileEntryWidth: function () {
		if (this.fileEntryWidth) {
			return this.fileEntryWidth;
		}
		var w;
		if (this.element.getWidth() != 0) {
			w = this.element.getWidth() - 122;
		} else { 
			w = this.element.style.width - 122;
		}
		this.fileEntryWidth = w;
		var progressW = this._progressBar.style.width;
		if (progressW == "") { progressW = 200; }
		if (progressW > this.fileEntryWidth) {
			this._progressBar.style.width = w;
			var r  = $(this._progressBar.id + ":remain");
			if (r) {
				r.style.width = w;
				$(this._progressBar.id + ":complete").style.width = w;
			}
		}
		return this.fileEntryWidth;
	},
	
	createFrame: function () {
		var div = document.createElement("div");
			div.style.display = 'none';
		var child = "<iframe name='"+this.id+"_iframe' id='"+this.id+"_iframe'></iframe>";
			div.innerHTML = child;
		document.body.appendChild(div);
		var iframe = $(this.id + "_iframe");
		this.iframe = iframe;
		return iframe;
	},
	
	checkFrame: function () {
		this.iframe = $(this.id + "_iframe");
		if (this.iframe) {
			this.deleteFrame();
		}
	},
	
	deleteFrame: function() {
	if (this.iframe) {
		this.iframe.src = "about:blank";
		document.body.removeChild(this.iframe.parentNode);
	}
		this.iframe = null;
	},
	
	initEvents : function() {
		for (var e in this.events) {
			if (e && this.events[e]) {
				if(e == 'onupload') {
					this.element.observe("rich:onupload", function(event) {
						if(this.events['onupload'](event) !== false) {
							event.memo.entry.upload();
						}
					}.bindAsEventListener(this));
				} else {
					this.element.observe("rich:" + e, this.events[e]);
				}
			}
		}
	},

	getFileSize: function (data) {
	if (!this.labelMarkup) return;
	if (data) {
		var progressData = new ProgressData(data);
		this.progressData = progressData;
		if (this.activeEntry) {
			this.activeEntry.setupLabelUpdate();
		}
	}else {
		if (this.activeEntry)
			this.getFileSizeScript(this.activeEntry.uid, this.formId);
	}
	},

	prepareProgressBar: function () {
		this.progressBar.setValue(0);
		Element.show(this._progressBar);
		this.progressBar.enable();
	},
	
	finishProgressBar: function () {
		this.progressBar.disable();
		this.progressBar.setValue(100);
		Element.hide(this._progressBar);
	},
	
	setupAutoUpload: function() {
		this.runUpload = this.options.autoUpload;
	},
	
	checkFileType: function (fileName) {
	if (!this.acceptedTypes || this.acceptedTypes['*']) { return true; }
		if (/(?:\S+)\.(\S+)$/.test(fileName)) {
			var type = RegExp.$1;
			type = type.toLowerCase();
			if (this.acceptedTypes[type]) {
				return true;
			}
		}
		return false;
	},

	add: function(elt) {
		if (this.disabled) return;
		if (!this.checkFileType(elt.value)) return;
		var newEntry = new FileUploadEntry(elt, this);
		this.entries.push(newEntry);

		if (this.runUpload) {
			newEntry.setState(FileUploadEntry.READY);
		} else {
			newEntry.setState(FileUploadEntry.INITIALIZED);
		}

		var newUpload = elt.cloneNode(true);
		elt.onchange = null;
		elt.style.cssText = "position: absolute; right: 0px; top: 0px; display: none; visibility: hidden;";
		newUpload.id = this.id + ":file" + (this.idCounter++);
		this.currentInput = newUpload;
		elt.parentNode.appendChild(newUpload);

		if (this.runUpload) {
			this.upload();
		}

	},

	remove: function(entry) {
		entry.clear();
		this.entries = this.entries.without(entry);

	},

	_selectEntryForUpload: function() {
		var l = this.entries.length;
		for (var i = 0; i < l; i++) {
			var entry = this.entries[i];
			if (entry.state == FileUploadEntry.READY || entry.state == FileUploadEntry.INITIALIZED || entry.state == FileUploadEntry.UPLOAD_CANCELED) {

				return entry;
			}
		}

		return null;
	},

	upload: function() {
		if (this.disabled) return;

		this.runUpload = true;

		if (!this.activeEntry) {
			//no upload is being run now

			var entry2upload = this._selectEntryForUpload();
			if (entry2upload) {
				if(this.events.onupload) {
					this.element.fire("rich:onupload", {entry : entry2upload});
				} else {
					entry2upload.upload();
				}
			}
		}
	},

	stop: function() {
	if (this.disabled) return;
		this.runUpload = false;

		if (this.activeEntry) {
			this.activeEntry.stop();
		}
	},

	clear: function(entry) {
	if (this.disabled) return;
		if (entry) {
			this.remove(entry);
		} else {
			//this.entries.length should be evaluated every time!
			var i = 0;
			while (i < this.entries.length) {
				var entry = this.entries[i];
				if (entry.state == FileUploadEntry.UPLOAD_SUCCESS) {
					this.remove(entry);
				} else {
					i++;
				}
			}
		}
		
		if (this.entries.length == 0) {
			this.setupAutoUpload();
		}
		this.processButtons();
	},

	processButtons: function () {
		this.disableAddButton();
		this.disableCleanButton();
		this.disableUploadButton();
		this.switchUploadButton();
	},

	cleanAllDisabled: function () {
	if (this.options['autoclear']) return true;
		var c = this.getFileEntriesSumByState(FileUploadEntry.UPLOAD_SUCCESS);
		return (c == 0);
	},
	
	uploadAllDisabled: function () {
		if (this.runUpload && this.activeEntry) {
				return false;
		} else {
			var c = this.getFileEntriesSumByState(FileUploadEntry.READY, FileUploadEntry.INITIALIZED, FileUploadEntry.UPLOAD_CANCELED);
			return (c == 0);
		}
	},
	
	getFileEntriesSumByState: function () {
		var statuses = {}
		var s = 0;
		for (var i = 0; i < arguments.length; i++) {
			statuses[arguments[i]] = true;
		}
		for (var i = 0; i < this.entries.length; i++) {
			if (statuses[this.entries[i].state]) {
				s++;
			}
		}
		return s;
	},
	
	switchUploadButton: function () {
		if (this.runUpload) {
			var d = $(this.id + ":upload2");
			d.innerHTML = FileUploadEntry.LABELS['stop'];
			d.onclick = function () {
				this.stop();
			}.bind(this);
		}else {
			var d = $(this.id + ":upload2");
			d.innerHTML = FileUploadEntry.LABELS['upload'];;
			d.onclick = function () {
				this.upload();
			}.bind(this);
		}
	},

	disableCleanButton: function() {
		var disabled = this.cleanAllDisabled();
		var d1 = $(this.id + ":clean1");
		var d2 = $(this.id + ":clean2");
		if (disabled) {
			Element.hide(d1.parentNode);
			return;
		} else { 
			Element.show(d1.parentNode);
		}
		
	  	if(this.disabled) {
    		d1.onclick = function() {return false;};
    	} else {
    		d1.onclick = function() {return this.clear();}.bind(this);
    	}
    	this._updateClassNames(d1, d2, this.classes.CLEAN, this.classes.CLEAN_CONTENT);
    	
    },

    disableAddButton: function() {
    	var disabled = ((this.getFileEntriesSumByState(FileUploadEntry.READY, FileUploadEntry.INITIALIZED, FileUploadEntry.UPLOAD_CANCELED) + this.uploadedCount + this.getFileEntriesSumByState(FileUploadEntry.UPLOAD_IN_PROGRESS)) >= this.maxFileBatchSize);
    	this.currentInput.disabled = disabled || this.disabled;
    	var _disabled = this.disabled;
    	var d1 = $(this.id+":add1");
    	var d2 = $(this.id+":add2");
    	if (disabled) {
    		this.disabled = true;
    	}
    	this._updateClassNames(d1, d2, this.classes.ADD, this.classes.ADD_CONTENT);
    	this.disabled = _disabled;
    },

    disableUploadButton: function () {
    	var disabled = this.uploadAllDisabled();
    	var d1 = $(this.id + ":upload1");
    	var d2 = $(this.id + ":upload2");
    	if(disabled) {
    		Element.hide(d1.parentNode);
    	} else {
    		Element.show(d1.parentNode);
    	}
    	if (this.disabled) {
    		d1.onclick = function() {return false;};
    	}else {
    		d1.onclick = function() { return this.upload();}.bind(this);
    	}
    	this._updateClassNames(d1, d2, (this.runUpload) ? this.classes.CANCEL : this.classes.UPDATE, (this.runUpload) ? this.classes.CANCEL_CONTENT : this.classes.UPDATE_CONTENT);
    },
    
    _updateClassNames: function (d1,d2,buttonClass,buttonContentClass) {
    	if (this.disabled) {
    		d1.className = buttonClass.DISABLED;
    		d2.className = buttonContentClass.DISABLED;
    		d1.onmouseover = d1.onmouseout = d1.onmousedown = d1.onmouseup = null;
    	}else {
    		d1.className = buttonClass.ENABLED;
    		d2.className = buttonContentClass.ENABLED;
    		d1.onmouseover = function () {this.className='rich-fileupload-button-light rich-fileupload-font';};
    		d1.onmouseout = function () {this.className='rich-fileupload-button rich-fileupload-font';};
    		d1.onmousedown = function () {this.className='rich-fileupload-button-press rich-fileupload-font';};
    		d1.onmouseup = function () {this.className='rich-fileupload-button rich-fileupload-font';};
    	}
    },
    
    disable: function () {
    	this.disabled = true;
    	this.items.className = "rich-fileupload-list-overflow " + this.classes.UPLOAD_LIST.DISABLED;
    	for (var i = 0; i < this.entries.length; i++) {
    		var entry = this.entries[i];
    		entry.entryElement.rows[0].cells[0].className = "rich-fileupload-font rich-fileupload-name rich-fileupload-table-td " + this.classes.FILE_ENTRY.DISABLED;
    		entry.controlArea.firstChild.className = "rich-fileupload-anc " + this.classes.FILE_ENTRY_CONTROL.DISABLED;
    	} 
    	this.processButtons();
    },
    
    enable: function () {
    	this.disabled = false;
    	this.items.className = "rich-fileupload-list-overflow " + this.classes.UPLOAD_LIST.ENABLED;
    	for (var i = 0; i < this.entries.length; i++) {
    		var entry = this.entries[i];
    		entry.entryElement.rows[0].cells[0].className = "rich-fileupload-font rich-fileupload-name rich-fileupload-table-td " + this.classes.FILE_ENTRY.ENABLED;
    		entry.controlArea.firstChild.className = "rich-fileupload-anc " + this.classes.FILE_ENTRY_CONTROL.ENABLED;
    	} 
    	this.processButtons();
    },

	_endUpload: function() {
		if (this.options['autoclear']) {
			this.clear(this.activeEntry);
		}
		this.activeEntry = null;
		this.deleteFrame();
	},
	
	updateViewState: function (state) {
		if (!state) return;
		var form = this.getForm();
		var viewStateE  = form['javax.faces.ViewState'];
		if (viewStateE) {
			viewStateE.value = state;
		}
	},
	
	_updateEntriesState: function() {
		var l = this.entries.length;
		
		var oldState;
		var newState;
		
		if (this.runUpload) {
			oldState = FileUploadEntry.INITIALIZED;
			newState = FileUploadEntry.READY;
		} else {
			oldState = FileUploadEntry.READY;
			newState = FileUploadEntry.INITIALIZED;
		}
		
		for (var i = 0; i < l; i++) {
			var entry = this.entries[i];
			if (entry.state == oldState) {
				entry.setState(newState);
			}
		}
	},
	
	notifyStateChange: function(entry, oldState) {
		var newState = entry.state;
		
		if (newState == FileUploadEntry.UPLOAD_SUCCESS || newState == FileUploadEntry.UPLOAD_SIZE_ERROR) {
			//todo clear completed
		
			if (newState == FileUploadEntry.UPLOAD_SUCCESS) {
				this.uploadedCount++;
			}
			
			this._endUpload();
			
			var entry = this._selectEntryForUpload();
			if (entry) {
				if (this.runUpload) {
					entry.upload();
				}
			} else {
				//we've uploaded all files sucessfully
				//but this.runUpload can be false if upload
				//has been requested to stop by user 
				this.setupAutoUpload();
				if(this.events.onuploadcomplete) {
					this.element.fire("rich:onuploadcomplete", {});
				}
			}

			this._updateEntriesState();

		} else if (newState == FileUploadEntry.UPLOAD_CANCELED ||
				newState == FileUploadEntry.UPLOAD_TRANSFER_ERROR ||
				newState == FileUploadEntry.UPLOAD_SERVER_ERROR) {

			
			this._endUpload();

			this.runUpload = false;
			
			this._updateEntriesState();

			if(newState == FileUploadEntry.UPLOAD_CANCELED) {
				if(this.events.onuploadcanceled) {
					this.element.fire("rich:onuploadcanceled", {});
				}
			} else {
				if(this.events.onerror) {	
					this.element.fire("rich:onerror", {});
				}
			}

		} else if (newState == FileUploadEntry.UPLOAD_IN_PROGRESS) {
		
			this.activeEntry = entry;
		
			this._updateEntriesState();

		}
		this.processButtons();
	},
	
	getForm: function () {
		return this.form;
	},
	
	_getForm: function () {
		var parentForm = this.element;
		while (parentForm.tagName && parentForm.tagName.toLowerCase() != 'form') {
			parentForm = parentForm.firstChild;
		}
		return parentForm;
	},
	
	submitForm: function(entry) {
		var parentForm = this.getForm();
		
		if (!parentForm) {
			throw "No parent form found!";
		}

		entry.uid = encodeURIComponent(Math.random().toString());
		
		var oldTarget = parentForm.target;
		var oldEnctype = parentForm.enctype;
		var oldEncoding = parentForm.encoding;
		var oldAction = parentForm.action;
		
		parentForm.encoding = "multipart/form-data"; 
		parentForm.enctype = "multipart/form-data"; 
		parentForm.target = this.id + "_iframe";//this.id;
		parentForm.action = oldAction + (/\?/.test(oldAction) ? '&_richfaces_upload_uid' : '?_richfaces_upload_uid') + '=' + encodeURI(entry.uid) + "&id=" + this.id;

		try {
			var inputs = parentForm.elements;
			var entryInput = entry.fileInput;
			
			entryInput.name = this.id + ":file";
			entryInput.disabled = false;

			var l = inputs.length;
			for (var i = 0; i < l; i++) {
				var input = inputs[i];
				if (input != entryInput) {
					if ('hidden' != input.type) {
					
						//FIXME: simulate ajax single request after it will be possible
						//input._name = input.name;
						//input.name = undefined;
						
						//TODO for test
						if ('file' == input.type) {
							input._disabled = input.disabled;
							input.disabled = true; 
						}
					}
				}
			}
	
			if (!parentForm.onsubmit || parentForm.onsubmit()) {
				var iframe = this.createFrame();
				new LoadWatcher(iframe, function(newState) {
					this.finishProgressBar();
					this.setState(newState);
				}.bind(entry),
				function (state) {
					this.updateViewState(state);
				}.bind(this));
				parentForm.submit();
			}
			
			for (var i = 0; i < l; i++) {
				var input = inputs[i];
				if ('hidden' != input.type) {
					//input.name = input._name;
					//input._name = undefined;
					
					if ('file' == input.type) {
						input.disabled = input._disabled;
						input._disabled = undefined; 
					}
				}
			}
		} finally {
			parentForm.action = oldAction;
			parentForm.target = oldTarget;
			parentForm.encoding = oldEncoding;
			parentForm.enctype = oldEnctype;
			this.getFileSizeScript(entry.uid, this.formId);
		}
	}
	
});

