'use strict';
'require view';
'require rpc';
'require form';
'require poll';


var callGetWgInstances = rpc.declare({
	object: 'luci.wireguard',
	method: 'getWgInstances'
});

function timestampToStr(timestamp) {
	if (timestamp < 1) {
		return _('Never');
	}
	var now = new Date();
	var seconds = (now.getTime() / 1000) - timestamp;
	var ago = '';
	if (seconds < 60) {
		ago = _('%ds ago').format(parseInt(seconds));
	} else if (seconds < 3600) {
		ago = _('%dm ago').format(parseInt(seconds / 60));
	} else if (seconds < 86401) {
		ago = _('%dh ago').format(parseInt(seconds / 3600));
	} else {
		ago = _('over a day ago');
	}
	var t = new Date(timestamp * 1000);
	return t.toUTCString() + ' (' + ago + ')';
}

function generatePeerOption(key, title, value) {
	return E('div', { 'class': 'cbi-value', 'style': 'padding: 0;' }, [
		E('label', {
			'class': 'cbi-value-title', 'style': 'font-weight: bold;'
		}, title),
		E('input', {
			'class': 'cbi-input-text',
			'data-name': key,
			'style': 'border: none; float: left; width: 50%;',
			'disabled': '',
			'value': value
		})
	]);
}

function generatePeerTable(options, iconSrc) {
	return E('div', { 'class': 'table cbi-section-table' }, [
		E('div', { 'class': 'td' },
			E('img', { 'src': iconSrc, 'class': 'tunnel-icon' })
		),
		E('div', { 'class': 'td peer-options' },
			options.filter(function (option) {
				return option[2] != null;
			}).map(function (option) {
				return generatePeerOption.apply(null, option);
			})
		)
	]);
}

function getTunnelIcon(latestHandshake) {
	var img = (new Date().getTime() / 1000 - latestHandshake) < 140 ?
		'tunnel' : 'tunnel_disabled';

	return L.resource('icons', img + '.png');
}

function generatePeerRows(peers) {
	var peerRows = [];

	peers.forEach(function (peer) {
		var peerData = parsePeerData(peer);
		var iconSrc = getTunnelIcon(peer.latest_handshake);

		peerRows.push(E('tr', {
			'class': 'tr cbi-section-table-row'
		}, [
			E('td', {
				'class': 'td peer-name',
				'style': 'width: 25%; font-size: 0.9rem;'
			}, peer.name),
			E('td', { 'class': 'td', 'data-section-id': peer.name },
				generatePeerTable(peerData, iconSrc)
			)
		]));
	});

	if (!peerRows.length) {
		peerRows.push(
			E('tr', { 'class': 'tr placeholder' },
				E('td', { 'class': 'td' },
					E('em', _('No peer information available')))));
	}

	return peerRows;
}

function parseIfaceData(iface) {
	return [
		['public_key', _('Public Key'),
			iface.public_key != '(none)' ? iface.public_key : null],
		['listen_port', _('Listen Port'),
			iface.listen_port > 0 ? iface.listen_port : null],
		['fwmark', _('Firewall Mark'),
			iface.fwmark != 'off' ? iface.fwmark : null]
	];
}

function parsePeerData(peer) {
	return [
		['public_key', _('Public Key'),
			peer.public_key],
		['endpoint', _('Endpoint'),
			peer.endpoint == '(none)' ? null : peer.endpoint],
		['allowed_ips', _('Allowed IPs'),
			peer.allowed_ips.length == 0 ? null : peer.allowed_ips.join('\n')],
		['persistent_keepalive', _('Persistent Keepalive'),
			peer.persistent_keepalive == 'off' ? null : peer.persistent_keepalive + 's'],
		['latest_handshake', _('Latest Handshake'),
			timestampToStr(peer.latest_handshake)],
		['transfer_rx', _('Data Received'),
			'%1024mB'.format(peer.transfer_rx)],
		['transfer_tx', _('Data Transmitted'),
			'%1024mB'.format(peer.transfer_tx)]
	];
}

return view.extend({
	load: function () {
		return callGetWgInstances();
	},

	poll_status: function (nodes, ifaces) {
		Object.keys(ifaces).forEach(function (ifaceName) {
			var iface = ifaces[ifaceName];

			var section = nodes.querySelector(
				'[data-section-id="%q"]'.format(ifaceName)
			);

			parseIfaceData(iface).forEach(function (option) {
				if (option[2] != null) {
					var optionEl = section.querySelector(
						'[data-name="%q"]'.format(option[0])
					);
					var inputEl = optionEl.querySelector('input');

					inputEl.value = option[2];
				}
			});

			iface.peers.forEach(function (peer) {
				var peerData = parsePeerData(peer);
				var iconSrc = getTunnelIcon(peer.latest_handshake);

				var peerSection = section.querySelector(
					'[data-section-id="%q"]'.format(peer.name)
				);
				var iconEl = peerSection.querySelector('.tunnel-icon');
				iconEl.src = iconSrc;

				peerData.forEach(function (option) {
					if (option[2]) {
						var inputEl = peerSection.querySelector(
							'[data-name="%q"]'.format(option[0])
						);
						inputEl.value = option[2];
					}
				})
			});
		});
	},

	render: function (ifaces) {
		var m, s, o, ss;

		m = new form.JSONMap(ifaces, _('WireGuard Status'));
		m.tabbed = true;

		var ifaceNames = Object.keys(ifaces);

		for (var i = ifaceNames.length - 1; i >= 0; i--) {
			var ifaceName = ifaceNames[i];
			var iface = ifaces[ifaceName];

			s = m.section(form.TypedSection, ifaceName);
			s.tabbed = true;
			s.anonymous = true;

			var ifaceData = parseIfaceData(iface);
			ifaceData.forEach(function (option) {
				if (option[2] != null) {
					o = s.option(form.Value, option[0], option[1]);
					o.readonly = true;
				}
			});

			o = s.option(form.SectionValue, 'peers', form.TypedSection, 'peers');
			ss = o.subsection;

			ss.render = L.bind(function (view, section_id) {
				return E('div', { 'class': 'cbi-section' }, [
					E('h3', _('Peers')),
					E('table', { 'class': 'table cbi-section-table' },
						generatePeerRows(this.peers))
				]);
			}, iface, this);
		}

		return m.render().then(L.bind(function (m, nodes) {
			if (!ifaceNames.length)
				nodes.appendChild(E('p', {}, E('em', _('No WireGuard interfaces configured.'))));

			poll.add(L.bind(function () {
				return callGetWgInstances().then(
					L.bind(this.poll_status, this, nodes)
				);
			}, this), 5);
			return nodes;
		}, this, m));
	},

	handleReset: null,
	handleSaveApply: null,
	handleSave: null
});
