var S3FlashUpload = new Class({
	Implements: [Options, Events],

	options: {
		form: null,
		progress: null,
		file: null,
		fakeFile: null,
		browse: null,
		s3BucketUri: null,
		s3Form: null,
		s3ContentType: null,
		s3FilePrefix: null,
		name: 'flashUpload',
		fieldName: 'fileName',
		maxUploadSize: 67108864,
		path: 'swiff.uploader.swf',
		messageMaxUploadSize: 'Please upload only files smaller than {maxUploadSize}.',
		messageUploadFailed: 'Upload "{file}" failed.',
		onSubmit: Class.empty,
		onUpload: Class.empty,
		onSelect: Class.empty,
		onSelectError: Class.empty,
		onError: Class.empty,
		onComplete: Class.empty,
		debug: false
	},

	initialize: function(options) {
		this.setOptions(options);
		if(!options.onSelectError) {
			this.addEvent('onSelectError', this.onSelectError);
		}
		if(!options.onError) {
			this.addEvent('onError', this.onError);
		}
		this.form = $(this.options.form);
		this.progress = $(this.options.progress);
		this.file = $(this.options.file);
		this.fakeFile = $(this.options.fakeFile);
		this.browse = $(this.options.browse);
		this.s3Form = $(this.options.s3Form);
		this.s3ContentType = $(this.options.s3ContentType);
		this.maxUploadSizeKB = this.sizeToKB(this.options.maxUploadSize);
		var messageMaxUploadSize = this.options.messageMaxUploadSize;
		var messageUploadFailed = this.options.messageUploadFailed;
		if(this.form && this.progress && this.file && this.fakeFile && this.browse && this.s3Form && this.s3ContentType) {
			if(Browser.Plugins.Flash.version >= 9 && !(Browser.Engine.webkit419 || Browser.Engine.presto925)) {
				this.swiffy = new Uploader(this.progress, {
					url: this.s3Form.action,
					id: this.options.name + 'Swiffy',
					fieldName: 'file',
					limitSize: this.options.maxUploadSize,
					path: this.options.path,
					target: this.browse,
					debug: this.options.debug,
					onLoad: function() {
						var id = this.file.getProperty('id');
						this.file.destroy();
						this.file = new Element('input', {
							'type': 'hidden',
							'name': this.options.fieldName,
							'value': ''
						}).inject(this.fakeFile, 'before');
						this.fakeFile.setProperty('id', id);
						this.fakeFile.removeClass('hidden');
						this.browse.removeClass('hidden');
					}.bind(this),
					onSelect: function(file) {
						if(file.size > this.options.maxUploadSize) {
							this.fireEvent('onSelectError', file);
							return false;
						}
						else {
							var fileName = file.name.trim();
							this.fakeFile.value = fileName;
							this.s3ContentType.value = MIMEtype.getType(fileName);
							this.fireEvent('onSelect', file);
							return true;
						}
					}.bind(this),
					fileError: function(file, error, info) {
						this.progress.addClass('hidden');
						this.file.value = '';
						this.fakeFile.value = '';
						this.fireEvent('onError', [file, error, info]);
					}.bind(this),
					fileUpload: function(file, options) {
						this.progress.removeClass('hidden');
						this.fireEvent('onUpload', file);
					}.bind(this),
					fileComplete: function(file, response) {
						this.file.value = this.options.s3BucketUri + encodeURIComponent(this.options.s3FilePrefix + file.name.trim());
						this.fireEvent('onComplete', {file: file, response: response});
						this.form.submit();
					}.bind(this)
				});
				this.browse.addEvent('click', function(event) {
					this.swiffy.browse();
					event.stop();
				}.bind(this));
			}
			else {
				this.swiffy = null;
			}
		}
	},

	delaySubmit: function(){
		this.form.submit();
	},

	submit: function() {
		if(this.swiffy && this.swiffy.files.length) {
			this.file.value = '';
			this.swiffy.upload({data: this.s3Form});
		}
		else {
			this.fireEvent('onSubmit');
			this.delaySubmit.delay(100, this);
		}
	},

	reposition: function() {
		if(this.swiffy) {
			this.swiffy.reposition();
		}
	},

	sizeToKB: function(size) {
		var unit = 'B';
		if((size / 1048576) > 1) {
			unit = 'MB';
			size /= 1048576;
		} else if((size / 1024) > 1) {
			unit = 'kB';
			size /= 1024;
		}
		return size.round(1) + ' ' + unit;
	},

	onSelectError: function(file) {
		var message = {maxUploadSize: this.maxUploadSizeKB};
		alert(this.options.messageMaxUploadSize.substitute(message));
	},

	onError: function(file, error, info) {
		var message = {file: file.name.trim()};
		alert(this.options.messageUploadFailed.substitute(message));
	}
})
