/**
 * Copyright © Mnemosyne LLC
 *
 * This file is licensed under the GPLv2.
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 */

function TorrentRendererHelper()
{
}

TorrentRendererHelper.getProgressInfo = function(controller, t)
{
	var pct, extra,
	    s = t.getStatus(),
	    seed_ratio_limit = t.seedRatioLimit(controller);

	if (t.needsMetaData())
		pct = t.getMetadataPercentComplete() * 100;
	else if (!t.isDone())
		pct = Math.round(t.getPercentDone() * 100);
	else if (seed_ratio_limit > 0 && t.isSeeding()) // don't split up the bar if paused or queued
		pct = Math.round(t.getUploadRatio() * 100 / seed_ratio_limit);
	else
		pct = 100;

	if (s === Torrent._StatusStopped)
		extra = 'paused';
	else if (s === Torrent._StatusDownloadWait)
		extra = 'leeching queued';
	else if (t.needsMetaData())
		extra = 'magnet';
	else if (s === Torrent._StatusDownload)
		extra = 'leeching';
	else if (s === Torrent._StatusSeedWait)
		extra = 'seeding queued';
	else if (s === Torrent._StatusSeed)
		extra = 'seeding';
	else
		extra = '';

	return {
		percent: pct,
		complete: [ 'torrent_progress_bar', 'complete', extra ].join(' '),
		incomplete: [ 'torrent_progress_bar', 'incomplete', extra ].join(' ')
	};
};

TorrentRendererHelper.createProgressbar = function(classes)
{
	var complete, incomplete, progressbar;

	complete = document.createElement('div');
	complete.className = 'torrent_progress_bar complete';

	incomplete = document.createElement('div');
	incomplete.className = 'torrent_progress_bar incomplete';

	progressbar = document.createElement('div');
	progressbar.className = 'torrent_progress_bar_container ' + classes;
	progressbar.appendChild(complete);
	progressbar.appendChild(incomplete);

	return { 'element': progressbar, 'complete': complete, 'incomplete': incomplete };
};

TorrentRendererHelper.renderProgressbar = function(controller, t, progressbar)
{
	var e, style, width, display,
	    info = TorrentRendererHelper.getProgressInfo(controller, t);

	// update the complete progressbar
	e = progressbar.complete;
	style = e.style;
	width = '' + info.percent + '%';
	display = info.percent > 0 ? 'block' : 'none';
	if (style.width!==width || style.display!==display)
		$(e).css({ width: ''+info.percent+'%', display: display });
	if (e.className !== info.complete)
		e.className = info.complete;

	// update the incomplete progressbar
	e = progressbar.incomplete;
	display = (info.percent < 100) ? 'block' : 'none';
	if (e.style.display !== display)
		e.style.display = display;
	if (e.className !== info.incomplete)
		e.className = info.incomplete;
};

TorrentRendererHelper.formatUL = function(t)
{
	return '↑ ' + Transmission.fmt.speedBps(t.getUploadSpeed());
};

TorrentRendererHelper.formatDL = function(t)
{
	return '↓ ' + Transmission.fmt.speedBps(t.getDownloadSpeed());
};

/****
*****
*****
****/

function TorrentRendererFull()
{
}
TorrentRendererFull.prototype =
{
	createRow: function()
	{
		var root, name, peers, progressbar, details, image, button;

		root = document.createElement('li');
		root.className = 'torrent';

		name = document.createElement('div');
		name.className = 'torrent_name';

		peers = document.createElement('div');
		peers.className = 'torrent_peer_details';

		progressbar = TorrentRendererHelper.createProgressbar('full');

		details = document.createElement('div');
		details.className = 'torrent_progress_details';

		image = document.createElement('div');
		button = document.createElement('a');
		button.appendChild(image);

		root.appendChild(name);
		root.appendChild(peers);
		root.appendChild(button);
		root.appendChild(progressbar.element);
		root.appendChild(details);

		root._name_container = name;
		root._peer_details_container = peers;
		root._progress_details_container = details;
		root._progressbar = progressbar;
		root._pause_resume_button_image = image;
		root._toggle_running_button = button;

		return root;
	},

	getPeerDetails: function(t)
	{
		var err,
		    peer_count,
		    webseed_count,
		    fmt = Transmission.fmt;

		if ((err = t.getErrorMessage()))
			return err;

		if (t.isDownloading())
		{
			peer_count = t.getPeersConnected();
			webseed_count = t.getWebseedsSendingToUs();

			if (webseed_count && peer_count)
			{
				// Downloading from 2 of 3 peer(s) and 2 webseed(s)
				return [ 'Downloading from',
				         t.getPeersSendingToUs(),
				         'of',
				         fmt.countString('peer','peers',peer_count),
				         'and',
				         fmt.countString('web seed','web seeds',webseed_count),
				         '-',
				         TorrentRendererHelper.formatDL(t),
				         TorrentRendererHelper.formatUL(t) ].join(' ');
			}
			else if (webseed_count)
			{
				// Downloading from 2 webseed(s)
				return [ 'Downloading from',
				         fmt.countString('web seed','web seeds',webseed_count),
				         '-',
				         TorrentRendererHelper.formatDL(t),
				         TorrentRendererHelper.formatUL(t) ].join(' ');
			}
			else
			{
				// Downloading from 2 of 3 peer(s)
				return [ 'Downloading from',
				         t.getPeersSendingToUs(),
				         'of',
				         fmt.countString('peer','peers',peer_count),
				         '-',
				         TorrentRendererHelper.formatDL(t),
				         TorrentRendererHelper.formatUL(t) ].join(' ');
			}
		}

		if (t.isSeeding())
			return [ 'Seeding to',
			         t.getPeersGettingFromUs(),
			         'of',
			         fmt.countString ('peer','peers',t.getPeersConnected()),
			         '-',
			         TorrentRendererHelper.formatUL(t) ].join(' ');

		if (t.isChecking())
			return [ 'Verifying local data (',
			         Transmission.fmt.percentString(100.0 * t.getRecheckProgress()),
			         '% tested)' ].join('');

		return t.getStateString();
	},

	getProgressDetails: function(controller, t)
	{
		if (t.needsMetaData()) {
			var MetaDataStatus = "retrieving";
			if (t.isStopped())
				MetaDataStatus = "needs";
			var percent = 100 * t.getMetadataPercentComplete();
			return [ "Magnetized transfer - " + MetaDataStatus + " metadata (",
			         Transmission.fmt.percentString(percent),
			         "%)" ].join('');
		}

		var c,
		    sizeWhenDone = t.getSizeWhenDone(),
		    totalSize = t.getTotalSize(),
		    is_done = t.isDone() || t.isSeeding();

		if (is_done) {
			if (totalSize === sizeWhenDone) // seed: '698.05 MiB'
				c = [ Transmission.fmt.size(totalSize) ];
			else // partial seed: '127.21 MiB of 698.05 MiB (18.2%)'
				c = [ Transmission.fmt.size(sizeWhenDone),
				      ' of ',
				      Transmission.fmt.size(t.getTotalSize()),
				      ' (', t.getPercentDoneStr(), '%)' ];
			// append UL stats: ', uploaded 8.59 GiB (Ratio: 12.3)'
			c.push(', uploaded ',
			       Transmission.fmt.size(t.getUploadedEver()),
			       ' (Ratio ',
			       Transmission.fmt.ratioString(t.getUploadRatio()),
			       ')');
		} else { // not done yet
			c = [ Transmission.fmt.size(sizeWhenDone - t.getLeftUntilDone()),
			      ' of ', Transmission.fmt.size(sizeWhenDone),
			      ' (', t.getPercentDoneStr(), '%)' ];
		}

		// maybe append eta
		if (!t.isStopped() && (!is_done || t.seedRatioLimit(controller)>0)) {
			c.push(' - ');
			var eta = t.getETA();
			if (eta < 0 || eta >= (999*60*60) /* arbitrary */)
				c.push('remaining time unknown');
			else
				c.push(Transmission.fmt.timeInterval(t.getETA()),
				       ' remaining');
		}

		return c.join('');
	},

	render: function(controller, t, root)
	{
		// name
		setTextContent(root._name_container, t.getName());

		// progressbar
		TorrentRendererHelper.renderProgressbar(controller, t, root._progressbar);

		// peer details
		var has_error = t.getError() !== Torrent._ErrNone;
		var e = root._peer_details_container;
		$(e).toggleClass('error',has_error);
		setTextContent(e, this.getPeerDetails(t));

		// progress details
		e = root._progress_details_container;
		setTextContent(e, this.getProgressDetails(controller, t));

		// pause/resume button
		var is_stopped = t.isStopped();
		e = root._pause_resume_button_image;
		e.alt = is_stopped ? 'Resume' : 'Pause';
		e.className = is_stopped ? 'torrent_resume' : 'torrent_pause';
	}
};

/****
*****
*****
****/

function TorrentRendererCompact()
{
}
TorrentRendererCompact.prototype =
{
	createRow: function()
	{
		var progressbar, details, name, root;

		progressbar = TorrentRendererHelper.createProgressbar('compact');

		details = document.createElement('div');
		details.className = 'torrent_peer_details compact';

		name = document.createElement('div');
		name.className = 'torrent_name compact';

		root = document.createElement('li');
		root.appendChild(progressbar.element);
		root.appendChild(details);
		root.appendChild(name);
		root.className = 'torrent compact';
		root._progressbar = progressbar;
		root._details_container = details;
		root._name_container = name;
		return root;
	},

	getPeerDetails: function(t)
	{
		var c;
		if ((c = t.getErrorMessage()))
			return c;
		if (t.isDownloading()) {
			var have_dn = t.getDownloadSpeed() > 0,
			    have_up = t.getUploadSpeed() > 0;
			if (!have_up && !have_dn)
				return 'Idle';
			var s = '';
			if (have_dn)
				s += TorrentRendererHelper.formatDL(t);
			if (have_dn && have_up)
				s += ' '
			if (have_up)
				s += TorrentRendererHelper.formatUL(t);
			return s;
		}
		if (t.isSeeding())
			return [ 'Ratio: ',
			         Transmission.fmt.ratioString(t.getUploadRatio()),
			         ', ',
			         TorrentRendererHelper.formatUL(t) ].join('');
		return t.getStateString();
	},

	render: function(controller, t, root)
	{
		// name
		var is_stopped = t.isStopped();
		var e = root._name_container;
		$(e).toggleClass('paused', is_stopped);
		setTextContent(e, t.getName());

		// peer details
		var has_error = t.getError() !== Torrent._ErrNone;
		e = root._details_container;
		$(e).toggleClass('error', has_error);
		setTextContent(e, this.getPeerDetails(t));

		// progressbar
		TorrentRendererHelper.renderProgressbar(controller, t, root._progressbar);
	}
};

/****
*****
*****
****/

function TorrentRow(view, controller, torrent)
{
	this.initialize(view, controller, torrent);
}
TorrentRow.prototype =
{
	initialize: function(view, controller, torrent) {
		var row = this;
		this._view = view;
		this._torrent = torrent;
		this._element = view.createRow();
		this.render(controller);
		$(this._torrent).bind('dataChanged.torrentRowListener',function(){row.render(controller);});

	},
	getElement: function() {
		return this._element;
	},
	render: function(controller) {
		var tor = this.getTorrent();
		if (tor)
			this._view.render(controller, tor, this.getElement());
	},
	isSelected: function() {
		return this.getElement().className.indexOf('selected') !== -1;
	},

	getTorrent: function() {
		return this._torrent;
	},
	getTorrentId: function() {
		return this.getTorrent().getId();
	}
};
