/*
	File upload progress bar.
	(c) 2008 Ingo Struck.
	All rights reserved.

	Roughly inspired by UberUpload (http://uber-uploader.sourceforge.net).
	The smoothing of the status bar, however, works completely different
	here and the status bar is styled in terms of percent, not px.
*/
var upload = {
	ini: false // initialized flag
	,cfg: { bar: {width: 400} }
	,tim: 0
	,eta: 0
	,siz: { tot: 0, cur: 0 }   // size of transmitted data in bytes: total, current
	,loop: { run: false, to: {stat: 1000, bar: 50, byte: 15}, step:0, max_step:0, min_step:1 } // update loop parameters
	,div: {} // DOM div access
	,sta: { bar: 0, cur: 0, rat: 0, bps: 0 } // status
	,dom: false
};

upload.onReady = function () {
	var upl = $('form_upl');
	if (null == upl) return;
	var uact = String(upl.action);
	var host = uact.replace(/^http:\/\/(\S*)\/.*$/,'$1');
	host = host.replace(/\/.*$/,'');
	var dom = host.replace(channel.the_dom,'');
	if (0 != dom.length) upload.dom = dom.substring(0,dom.length-1);

	for ( var i = 0; i < upl.elements.length; ++i ) {
		var elm = upl.elements[i];
		if ('sub' == elm.name ) upload.sub = elm;
		else if ('file0' == elm.name ) upload.upl = elm;
	}
	if (null == upload.sub || null == upload.upl) return;
	upl = null;

	var pro = document.createElement('div');
	pro.className = 'info_upl';
	pro.style.display = 'none';
	
	var bar = document.createElement('div');
	bar.className = 'progress';
	var pos = document.createElement('div');
	pos.style.width = '0';
	bar.appendChild(pos);
	pro.appendChild(bar);

	var chld = ['per','btx','bps','eta'];
	
	for (var idx = 0; idx < chld.length; ++idx ) {
		var c = document.createElement('div');
		var nam = chld[idx];
		c.className = nam;
		pro.appendChild(c);
		upload.div[nam] = c;
	}

	var parent = upload.sub.parentNode;
	parent.insertBefore( pro, upload.sub.nextSibling );

	upload.div.pro = pro;
	upload.div.bar = bar;
	upload.div.pos = pos;

	upload.sub.onclick = function () { upload.start(); }
	
	upload.ini = true;
	upload.onReady = null;
	upload.reset();
};

upload.showtime = function (time) {
	var pad = function (n) { return 10 > n ? '0'+n : ''+n; };
	var sec = time % 60;
	var min = ((time - sec) % 3600) / 60;
	return pad((((time - sec) - (min * 60)) % 86400) / 3600)+':'+pad(min)+':'+pad(sec);
};

upload.reset = function () {
	if (!upload.ini) return;
	upload.div.eta.innerHTML = '';
	upload.div.pos.style.width = '0';
	var wait = $('upl_wait');
	if (wait) wait.style.display = 'none';
	upload.upl.style.display = 'block';
	upload.sub.style.display = 'block';
};

upload.start = function () {
	if (!upload.ini) return;
	if (!upload.chk_files()) return;
	
	upload.reset();

	upload.upl.style.display = 'none';
	upload.sub.style.display = 'none';
	upload.div.pro.style.display = 'block';

	upload.loop.run = true;
	upload.tmr_tim = setInterval('upload.upd_tim()',500);
	upload.stat_loop(250); // get the first stat fast
};

upload.stop = function () {
	clearInterval(upload.tmr_tim);
	clearTimeout(upload.to_stat);
	upload.loop.step = 0.01;
	upload.sta.rat = 1;
	upload.sta.bar = 1;
	upload.show_stat();

	upload.div.pro.style.display = 'none';
	var wait = $('upl_wait');
	if (wait) wait.style.display = 'block';
};

upload.stat_loop = function (delay) {
	if ( null == delay ) delay = upload.loop.to.stat;
	upload.to_stat = setTimeout('channel.send(upload.dom, "/upmon?stamp='+(new Date()).getTime()+'", "GET", upload.stat_cb, false);', delay);
};
upload.stat_cb = function (res, status, headers) {
	if (200 != status) return;
	var per = 0;
	res = util.trim(res);
	if (0 == res.length) {
		upload.stop();
	} else {
		var val = res.split('\t');
		upload.calc_stat(val[0],val[1],val[2]);
		upload.show_stat();
		upload.stat_loop();
	}
};

upload.calc_stat = function (tot,cur,tim) {
	if (null == tot || 0 == tot || null == cur || 0 == cur) return;
	var bpms = 0; // bytes per millisec
	if (null == tim) tim = 0;
	if ( 0 < tim ) bpms = cur / tim;
	var loop = upload.loop;
	var to = loop.to;
	var ttot = 0;
	if ( 0 < bpms && 0 < cur) {
		upload.eta = Math.round((tot - cur) / (bpms*1000));
		ttot = tim * (1 + (tot-cur)/cur);
		loop.step = to.bar/ttot;
	} else {
		to.bar = 260;
		to.byte = 15;
	}

	var sta = upload.sta;
	sta.cur = cur;
	sta.bps = Math.round(bpms*1000);
	sta.rat = cur/tot;

	var delta = (sta.rat - sta.bar) * (loop.to.bar/loop.to.stat);
	loop.step += delta;

	var min_step = 0.0;
	var max_step = 0.0075;
	loop.step = Math.max(loop.step,min_step);
	loop.step = Math.min(loop.step,max_step);

	// immediately fix step size
	clearTimeout(upload.to_bar);
	upload.loop_bar();
};

upload.show_stat = function () {
	var prec = 100000;
	upload.div.pos.style.width = Math.round(100*upload.sta.bar*prec)/prec + '%';
};

upload.chk_files = function () {
	if (!upload.ini) return;
	return true;
};

upload.fmt_byte = function (byte) {
	if (1024>byte) return ''+byte+'B';
	byte = byte/1024;
	if (1024>byte) return ''+(Math.round(byte*10)/10)+'KB';
	byte = byte/1024;
	if (1024>byte) return ''+(Math.round(byte*10)/10)+'MB';
	byte = byte/1024;
	if (1024>byte) return ''+(Math.round(byte*10)/10)+'GB';
	byte = byte/1024;
	return ''+Math.round(byte)+'TB';
};

upload.upd_tim = function () {
	var sta = upload.sta;
	upload.div.per.innerHTML = Math.round(sta.rat*100)+'%';
	upload.div.btx.innerHTML = upload.fmt_byte(sta.cur);
	upload.div.bps.innerHTML = upload.fmt_byte(sta.bps)+'/s';
	upload.div.eta.innerHTML = upload.showtime(upload.eta);
};

upload.loop_bar = function () {
	var sta = upload.sta;
	var loop = upload.loop;
	var cfg = upload.cfg.bar.width;
	if (sta.bar <= 1 && 0 < loop.step) {
		sta.bar = sta.bar + loop.step;
		if (sta.bar > 1) {
			sta.bar = 1;
			loop.run = false;
		}
		upload.show_stat();
	}
	if (loop.run) {
		clearTimeout(upload.to_bar);
		upload.to_bar = setTimeout('upload.loop_bar()', loop.to.bar);
	}
};
