(function($) {
	var config = {
		cgiUploadURL: '',
		cgiProgressURL: '',
		progressBar: false
	};
	
	var url_init = function(cb){
		var wait_completion = function(){
			if(!url_init.complete)
				setTimeout(wait_completion, 300);
			else
				$.isFunction(cb) && cb();
		};
		
		if(url_init.done) {
			wait_completion();
			return;
		}
		url_init.done = true;
		
		var urls = [ (window.WEB_ROOT || '') + 'cgi-bin/', '/cgi-bin/' ];
		var step = 0;
		var errf = function(ev,req,set){
			ev.preventDefault();
			ev.stopPropagation();
			ev.stopImmediatePropagation();
			step++;
			testf();
			return false;
		};
		var testf = function(){
			if(!urls[step]) {
				url_init.complete = true;
				return;
			}
			if(!url_init.err_bind) {
				$(window).bind('ajaxError', errf);
				url_init.err_bind = true;
			}
			urls[step] = toAbsURL(urls[step]);
			$.get(urls[step] + 'progress.cgi', 'sessionid=test', function(html){
				if(html == 'OK') {
					$(window).unbind('ajaxError', errf);
					url_init.err_bind = false;
					config.progressBar = true;
					config.cgiUploadURL = urls[step] + 'upload.cgi';
					config.cgiProgressURL = urls[step] + 'progress.cgi';
					url_init.complete = true;
					return;
				}
				step++;
				testf();
			});
		};
		testf();
		
		wait_completion();
	}
	
	$(function(){
		url_init();
	});
	
	$.fn.smoothForm = function(options) {
	    if(!this.length || !$.fn.ajaxForm)
	        return this;
	    
	    var me = this;
	    url_init(function(){
		    overloadOptions(options);
	    	me.ajaxForm(options);
	    });
	    
	    return this;
	};
	
	$.fn.smoothSubmit = function(options) {
	    if(!this.length || !$.fn.ajaxSubmit)
	        return this;
	    
	    var me = this;
	    url_init(function(){
		    overloadOptions(options);
		    me.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());
		$(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/admin/buttons/remove_small.png" border="0" alt="Remove" style="vertical-align:middle"></a>');
		$('a', $(this).parent().parent()).click(function(){
			$(this).parent().slideUp(500, function(){
				$(this).remove();
			});
			return false;
		});
	}
	
	function overloadOptions(options) {
	    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) {
	    		if(config.progressBar) {
		    		var sid = generateSID();
		    		var redir = toAbsURL(options.url);
		    		var s = ''; for(var i in options) s+=i+': '+options[i]+'\n';
		    		if(options.cgiUploadURL || config.cgiUploadURL)
		    			options.url = (options.cgiUploadURL || config.cgiUploadURL) + '?' + 'sid='+sid+'&redirect_url='+escape(redir);
	    		}
    			showProgress(form, sid, options);
	    	}
	    	
	    	return true;
	    };
	    
	    var success = options.success;
	    options.success = function(res, status, xhr, form){
	    	if(xhr && xhr.jquery) form = xhr;
	    	var overlay = $(form).data('overlay');
	    	var progress = $(form).data('progress');
	    	if(overlay) overlay.fadeOut(500, function(){ overlay.remove(); });
	    	if(progress) progress.fadeOut(1000, function(){ progress.remove()});
	    	if($.isFunction(success) && success(res, status, xhr, form) === false)
	    		return false;
	    }
	}
	
	function showProgress(form, sid, opt) {
		var me = form;
		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.outerWidth();
		off.height = form.outerHeight();
		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);
		
		$(me).data('overlay', overlay);
		$(me).data('progress', div);
	}
	
	function getStatus(div, sid, overlay, opt, init_done, url) {
		if(!config.progressBar) {
			$('.progress-text1', div).html('Upload in progres...');
			$('.progress-text2', div).html('Please wait...');
			$('.progress-bar > div', div).css('width', '100%');
			return;
		}
		
		if(!init_done) {
			var ts = parseInt(new Date().getTime().toString().substring(0, 10));
			url = config.cgiProgressURL + '?iTotal=-1&iRead=0&iStatus=1&sessionid='+sid+'&dtnow='+ts+'&dtstart='+ts;
		}

		url = url.split(/\?/);
		$.getJSON(url[0], url[1]+'&rand='+Math.random(), function(data){
			if(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);
					return;
				}
			}
			if(opt.processing) {
				$('.progress-text1', div).html($(opt.processing).html());
				$('.progress-text2', div).html('Please wait...');
			}
		});
	}
	
	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);

