/**
* FancyUpload - Flash meets Ajax for beauty uploads
*
* Based on Swiff.Base and Swiff.Uploader.
*
* Its intended that you edit this class to add your
* own queue layout/text/effects. This is NO include
* and forget class. If you want custom effects or
* more output, use Swiff.Uploader as interface
* for your new class or change this class.
*
* USAGE:
*  var inputElement = $E('input[type="file"]');
* 	new FancyUpload(inputElement, {
* 		swf: '../swf/Swiff.Uploader.swf'
* 		// more options
* 	})
*
* 	The target element has to be in an form, the upload starts onsubmit
* 	by default.
*
* OPTIONS:
*
* 	url: Upload target URL, default is form-action if given, otherwise current page
*  swf: Path & filename of the swf file, default: Swiff.Uploader.swf
*  multiple: Multiple files selection, default: true
*  queued: Queued upload, default: true
*  types: Object with (description: extension) pairs, default: Images (*.jpg; *.jpeg; *.gif; *.png)
*  limitSize: Maximum size for one added file, bigger files are ignored, default: false
*  limitFiles: Maximum files in the queue, default: false
*  createReplacement: Function that creates the replacement for the input-file, default: false, so a button with "Browse Files" is created
*  instantStart: Upload starts instantly after selecting a file, default: false
*  allowDuplicates: Allow duplicate filenames in the queue, default: true
*  container: Container element for the swf, default: document.body, used only for the first FancyUpload instance, see QUIRKS
*  optionFxDuration: Fx duration for highlight, default: 250
*  queueList: The Element or ID for the queue list
*  onComplete: Event fired when one file is completed
*  onAllComplete: Event fired when all files uploaded
*
* NOTE:
*
* 	Flash FileReference is stupid, the request will have no cookies
* 	or additional post data. Only the file is send in $_FILES['Filedata'],
* 	with a wrong content-type (application/octet-stream).
* 	When u have sessions, append them as get-data to the the url.
*
*
* @version		1.0rc1
*
* @license		MIT License
*
* @author		Harald Kirschner <mail [at] digitarald [dot] de>
* @copyright	Authors
*/
var FancyUpload = new Class({
	options: {
		url: 'upload.php',
		swf: 'Swiff.Uploader.swf',
		multiple: false,
		queued: true,
		types: {'MP3 files (*.mp3)': '*.mp3'},
		limitSize: false,
		limitFiles: 1,
		createReplacement: null,
		instantStart: false,
		allowDuplicates: false,
		optionFxDuration: 1000,
		container: null,
		queueList: 'upload-queue',
		onComplete: Class.empty,
		onError: Class.empty,
		onCancel: Class.empty,
		onAllComplete: Class.empty
	},

	initialize: function(el, options){
		this.element = $(el);
		this.setOptions(options);
		this.options.url = this.options.url || this.element.form.action || location.href;
		this.fileList = [];

		this.uploader = new Swiff.Uploader({
			onOpen: this.onOpen.bind(this),
			onProgress: this.onProgress.bind(this),
			onComplete: this.onComplete.bind(this),
			onError: this.onError.bind(this),
			onSelect: this.onSelect.bind(this)
		}, this.initializeFlash.bind(this), {
			swf: this.options.swf,
			types: this.options.types,
			multiple: this.options.multiple,
			queued: this.options.queued,
			container: this.options.container
		});
	},

	initializeFlash: function() {
		this.queue = $(this.options.queueList);
		$(this.element.form).addEvent('submit', this.upload.bindWithEvent(this));
		if (this.options.createReplacement) this.options.createReplacement(this.element);
	else {
		new Element('input', {
			type: 'button',
			value: 'Browse Files',
			events: {
				click: this.browse.bind(this)
			}
		}).injectBefore(this.element);
		this.element.remove();
	}

},

browse: function() {
	this.uploader.browse();
},

upload: function(e) {
	if (e) e.stop();
	this.uploader.send(this.options.url);
},

onSelect: function(name, size) {
	if (this.uploadTimer) this.uploadTimer = $clear(this.uploadTimer);
	if ((this.options.limitSize && (size > this.options.limitSize))
	|| (this.options.limitFiles && (this.fileList.length >= this.options.limitFiles))
	|| (!this.options.allowDuplicates && this.findFile(name, size) != -1)) return false;
	this.addFile(name, size);
	if (this.options.instantStart) this.uploadTimer = this.upload.delay(250, this);
	return true;
},

onOpen: function(name, size) {
	var index = this.findFile(name, size);
	this.fileList[index].status = 1;
	if (this.fileList[index].fx) return;
	this.fileList[index].fx = new Element('div', {'class': 'queue-subloader','id': 'completed'}).injectInside(
	new Element('div', {'class': 'queue-loader'}).setHTML('<span>Uploading</span>').injectInside(this.fileList[index].element)
	).effect('width', {
		duration: 200,
		wait: false,
		unit: '%',
		transition: Fx.Transitions.linear
	}).set(0);
},

onProgress: function(name, bytes, total, percentage) {
	this.uploadStatus(name, total, percentage);
},

onComplete: function(name, size) {
	var index = this.uploadStatus(name, size, 100);
	this.fileList[index].fx.element.setHTML('Completed!');
	this.fileList[index].status = 2;
	this.highlight(index, 'e1ff80');
	this.checkComplete(name, size, 'onComplete');
	this.showRes();
},

showRes: function()
{
	xmlHttp=this.GetXmlHttpObject();
	if (xmlHttp==null)
	{
		return;
	}
	var url="result.php";
	xmlHttp.onreadystatechange=this.stateChanged;
	xmlHttp.open("GET",url,true);
	xmlHttp.send(null);
},

stateChanged: function()
{
	if (xmlHttp.readyState==4)
	{
		document.getElementById("completed").innerHTML = "Completed!<br>" + xmlHttp.responseText;
	}
},

GetXmlHttpObject: function()
{
	var xmlHttp=null;
	try
	{
		// Firefox, Opera 8.0+, Safari
		xmlHttp=new XMLHttpRequest();
	}
	catch (e)
	{
		// Internet Explorer
		try
		{
			xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e)
		{
			xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
		}
	}
	return xmlHttp;
},

/**
* Error codes are just examples, customize them according to your server-errorhandling
*
*/
onError: function(name, size, error) {
	var msg = "Upload failed (" + error + ")";
	switch(error.toInt()) {
		case 500: msg = "Internal server error, please contact Administrator!"; break;
		case 400: msg = "Upload failed, please check your filesize!"; break;
		case 409: msg = "Could not process image, please choose another!"; break;
		case 415: msg = "Unsupported media type, please upload GIF, PNG, TIFF or JPEG!"; break;
		case 412: msg = "Invalid target, please reload page and try again!"; break;
		case 417: msg = "Photo too small, please keep our photo manifest in mind!"; break;
	}
	var index = this.uploadStatus(name, size, 100);
	this.fileList[index].fx.element.setStyle('background-color', '#ffd780').setHTML(msg);
	this.fileList[index].status = 2;
	this.highlight(index, 'ffd780');
	this.checkComplete(name, size, 'onError');
},

checkComplete: function(name, size, fire) {
	this.fireEvent(fire, [name, size]);
	if (this.nextFile() == -1) this.fireEvent('onAllComplete');
},

addFile: function(name, size) {
	if (!this.options.multiple && this.fileList.length) this.remove(this.fileList[0].name, this.fileList[0].size);
	this.fileList.push({
		name: name,
		size: size,
		status: 0,
		percentage: 0,
		element: new Element('li').setHTML('<span class="queue-file">'+ name +'</span><span class="queue-size" title="'+ size +' byte">~'+ Math.ceil(size / 1000) +' kb</span>').injectInside(this.queue)
	});
	new Element('a', {
		href: 'javascript:void(0)',
		'class': 'input-delete',
		title: 'Remove from queue',
		events: {
			click: this.cancelFile.bindWithEvent(this, [name, size])
		}
	}).injectBefore(this.fileList.getLast().element.getFirst());
	this.highlight(this.fileList.length - 1, 'e1ff80');
},

uploadStatus: function(name, size, percentage) {
	var index = this.findFile(name, size);
	this.fileList[index].fx.start(percentage).element.setHTML(percentage +'%');
	this.fileList[index].percentage = percentage;
	return index;
},

uploadOverview: function() {
	var l = this.fileList.length, i = -1, percentage = 0;
	while (++i < l) percentage += this.fileList[i].percentage;
	return Math.ceil(percentage / l);
},

highlight: function(index, color) {
	return this.fileList[index].element.effect('background-color', {duration: this.options.optionFxDuration}).start(color, 'fff');
},

cancelFile: function(e, name, size) {
	e.stop();
	this.remove(name, size);
},

remove: function(name, size, index) {
	if (name) index = this.findFile(name, size);
	if (index == -1) return;
	if (this.fileList[index].status < 2) {
		this.uploader.remove(name, size);
		this.checkComplete(name, size, 'onCancel');
	}
	this.fileList[index].element.effect('opacity', {duration: this.options.optionFxDuration}).start(1, 0).chain(Element.remove.pass([this.fileList[index].element], Element));
	this.fileList.splice(index, 1);
	return;
},

findFile: function(name, size) {
	var l = this.fileList.length, i = -1;
	while (++i < l) if (this.fileList[i].name == name && this.fileList[i].size == size) return i;
	return -1;
},

nextFile: function() {
	var l = this.fileList.length, i = -1;
	while (++i < l) if (this.fileList[i].status != 2) return i;
	return -1;
},

clearList: function(complete) {
	var i = -1;
	while (++i < this.fileList.length) if (complete || this.fileList[i].status == 2) this.remove(0, 0, 0, i--);
}
});


FancyUpload.implement(new Events, new Options);