(function($) {
	$.fn.smoothForm = function(options) {
	    if(!this.length || !$.fn.ajaxForm)
	        return this;
	    
	    overloadOptions(options);
	    this.ajaxForm(options);
	    
	    return this;
	};
	
	$.fn.smoothSubmit = function(options) {
	    if(!this.length || !$.fn.ajaxSubmit)
	        return this;
	    
	    overloadOptions(options);
	    this.ajaxSubmit(options);
	    
	    return this;
	};
	
	$.fn.smoothMulti = function(options) {
	    if(!this.length)
	        return this;
	    return this.each(function(){
	    	$(this).change(onMultiChange);
	    });
	};
	
	function onMultiChange() {
		$('<input type="file" name="'+$(this).attr('name')+'" value="" class="smoothMulti" style="clear:both;">')
			.change(onMultiChange)
			.appendTo($(this).parent());
			$('#uploadMore').remove();
		$(this)
			.wrap('<div style="width:auto; clear:both; color:#fff; margin-bottom:6px;"><div style="display:none;"></div></div>')
			.parent().before($(this).val() + ' <a href="#"><img src="images/design/buttons/remove_small.png" border="0" alt="Remove" style="vertical-align:middle"></a>');
		$(this).parent().before( '<div id="uploadMore">Add Another Photo</div>');
		$('a', $(this).parent().parent()).click(function(){
			$(this).parent().slideUp(200, function(){
				$(this).remove();
			});
			$('#uploadMore').remove();
			$(this).parent().before( '<div id="uploadMore">Add Another Photo</div>');
			return false;
		});
	}
	
	function overloadOptions(options) {
	    if(!options.cgiUploadURL)
	    	options.cgiUploadURL = '/cgi-bin/upload.cgi';
	    
	    var beforeSubmit = options.beforeSubmit;
	    options.beforeSubmit = function(data, form, options){
	    	if($.isFunction(beforeSubmit) && beforeSubmit(data, form, options) === false)
	    		return false;
	    	if(options.type.toUpperCase() != 'POST')
	    		return true;
	    	
	    	var overload = false;
	    	$('input:file', form).each(function(){ if(this.value) { overload = true; return false; } });
	    	
	    	if(overload) {
	    		var sid = generateSID();
	    		var redir = toAbsURL(options.url);
	    		options.url = options.url.split('?')[1];
	    		options.url = toAbsURL(options.cgiUploadURL) + '?' + 'sid='+sid+'&redirect_url='+escape(redir);
	    		
	    		showProgress(form, sid, options);
	    	}
	    	
	    	return true;
	    };
	}
	
	function showProgress(form, sid, opt) {
		var div = $('<div class="smoothform"><div class="progress-text1">&nbsp;</div><div class="progress-bar"><div style="width:0px"></div></div><div class="progress-text2">&nbsp;</div></div>');
		form = form.offsetParent();
		var off = form.offset();
		off.width = form.width();
		off.height = form.height();
		div.css({
			position: 'absolute',
			left: '0px',
			top: '0px',
			opacity: 0.0,
			zIndex: 9940
		}).appendTo(form);
		div.css({
			left: (off.width - div.width()) / 2 + 'px',
			top: (off.height - div.height()) / 2 + 'px'
		});
		var overlay = $('<div/>').css({
			position: 'absolute',
			left: '0px',
			top: '0px',
			background: opt.overlayColor || '#333',
			opacity: 0.0,
			width: off.width + 'px',
			height: off.height + 'px',
			zIndex: 9920
		}).appendTo(form);
		
		getStatus(div, sid, overlay, opt);
		
		overlay.fadeTo(500, 0.7);
		div.fadeTo(500, 1.0);
	}
	
	function getStatus(div, sid, overlay, opt, init_done, url) {
		if(!init_done) {
			var ts = parseInt(new Date().getTime().toString().substring(0, 10));
			url = '/cgi-bin/progress.cgi?iTotal=-1&iRead=0&iStatus=1&sessionid='+sid+'&dtnow='+ts+'&dtstart='+ts;
		}

		url = url.split(/\?/);
		$.getJSON(url[0], url[1], function(data){
			url = data.url;
			var sent = data.sent >= 1048576 ? parseFloat(data.sent / 1048576).toFixed(2) + 'M' : parseInt(data.sent / 1024) + 'K';
			var total = data.total >= 1048576 ? parseFloat(data.total / 1048576).toFixed(2) + 'M' : parseInt(data.total / 1024) + 'K';
			$('.progress-text1', div).html(data.total > 0 ? sent + '/' + total + ' (' + parseInt(data.sent * 100 / data.total) + '%) - ' +
					parseFloat(data.kbps/8).toFixed(2) + ' K/sec' : data.statusText);
			$('.progress-bar > div', div).css('width', parseInt(data.sent * 100 / data.total) + '%');
			$('.progress-text2', div).html(data.sent == data.total && data.total > 0 ? data.statusText :
					(data.total > 0 ? formatTime(data.elapsed_time) + '/' + formatTime(parseInt(data.elapsed_time) + parseInt(data.remaining_time)) : '&nbsp;')
				);
			if(data.status != 2) {
				window.setTimeout(function() { getStatus(div, sid, overlay, opt, true, url); }, 2000);
			} else {
				if(opt.processing) {
					$('.progress-text1', div).html($(opt.processing).html());
					$('.progress-text2', div).html('Please wait...');
				} else {
					overlay.fadeOut(500, function(){ overlay.remove(); });
					div.fadeOut(1000, function(){ div.remove()});
				}
			}
		});
	}
	
	function generateSID() {
		var chars = '0123456789abcdef';
		var sid = '';
		for(var i = 0; i < 32; i++)
			sid += chars.charAt(Math.floor(Math.random() * chars.length));
		return sid;
	}
	
	function toAbsURL(s) {
		var l = location, h, p, f, i;
		if(/^\w+:\/\//.test(s))
			return s;

		h = l.protocol + '//' + l.host;
		if(s.indexOf('/') == 0)
			return h + s;
		
		p = l.pathname.replace(/\/[^\/]*$/, '');
		if(f = s.match(/\.\.\//g)) {
			s = s.substring(f.length * 3);
			for(i = f.length; i--;)
				p = p.substring(0, p.lastIndexOf('/'));
		}

		return h + p + '/' + s;
	}

	function formatTime(tm) {
		var m = '00' + parseInt(tm / 60 % 60).toFixed(0);
		m = m.substring(m.length - 2);
		var s = '00' + parseInt(tm % 60).toFixed(0);
		s = s.substring(s.length - 2);
		var h = parseInt(tm / 3600).toFixed(0);
		if(h.toString().length < 2)
			h = ('00' + h).substring(h.length);
		return h + ':' + m + ':' + s;
	}
	
})(jQuery);