var params = JSON.parse(value);

var request = new HttpRequest();

request.addHeader('X-Cisco-Meraki-API-Key:' + params.token);
request.addHeader('User-Agent: ZabbixServer/1.2 Zabbix');

var response,
	error_msg = '',
	organization_devices = [],
	licenses = [];

function getField(data, path) {
	var steps = path.split('.');
	for (var i = 0; i < steps.length; i++) {
		var step = steps[i];
		if (typeof data !== 'object' || typeof data[step] === 'undefined') {
			throw 'Required field was not found: ' + path;
		}
		data = data[step];
	}

	return data;

};

function getHttpData(url) {
	var startTime = new Date().getTime();
	var maxWait = 1 * 60 * 60 * 1000;
	var waitFor = 1000;
	
	while (true) {
		response = request.get(url);
		Zabbix.log(4, '[ Meraki API ] [ ' + url + ' ] Received response with status code ' + request.getStatus() + ': ' + response);
	
		var status = request.getStatus();
	
		if (response !== null) {
			try {
				response = JSON.parse(response);
			}
			catch (error) {
				throw 'Failed to parse response received from Meraki API. Check debug log for more information.';
			}
		}
	
		if (status === 429 && response && response.errors && Array.isArray(response.errors) &&
			response.errors.indexOf("API rate limit exceeded for organization") !== -1) {
			var now = new Date().getTime();
			var headers = request.getHeaders(false);

			if ('Retry-After' in headers) {
				var retryAfter = headers['Retry-After'];
				Zabbix.log(4, '[ Meraki API ] API rate limit exceeded. Retrying after ' + retryAfter + ' seconds.');				 
				waitFor = parseInt(retryAfter) * 1000;
			}
			else {
				Zabbix.log(4, '[ Meraki API ] API rate limit exceeded. No Retry-After header. Retrying after 1 second.');
			}
			if (now - startTime + waitFor > maxWait) {
				throw 'Failed to receive data: API rate limit exceeded and retry timeout reached.';
			}
			Zabbix.sleep(waitFor);
			continue;
		}
	
		if (status !== 200) {
			if (response.errors) {
				throw response.errors.join(', ');
			}
			else {
				throw 'Failed to receive data: invalid response status code.';
			}
		}
	
		if (typeof (response) !== 'object' || response === null) {
			throw 'Cannot process response data: received data is not an object.';
		}
	
		return response;
	}
};

try {

	if (params.token === '{' + '$MERAKI.TOKEN}') {
		throw 'Please change {' + '$MERAKI.TOKEN} macro to the proper value.';
	}

	if (params.url.indexOf('http://') === -1 && params.url.indexOf('https://') === -1) {
		params.url = 'https://' + params.url;
	}

	if (!params.url.endsWith('/')) {
		params.url += '/';
	}

	if (typeof params.httpproxy !== 'undefined' && params.httpproxy !== '') {
		request.setProxy(params.httpproxy);
	}

	licenses = getHttpData(params.url + 'organizations/' + encodeURIComponent(params.organizationId) + '/licenses');

	organization_devices = getHttpData(params.url + 'organizations/' + encodeURIComponent(params.organizationId) + '/devices/statuses');

	licenses.forEach(function (license) {

		license.deviceName = getField(license, 'deviceSerial');

		for (i in organization_devices) {

			if (getField(license, 'deviceSerial') === getField(organization_devices[i], 'serial')) {

				device_name = getField(organization_devices[i], 'name');

				if (!device_name) {
					device_name = getField(organization_devices[i], 'serial');
				}
				license.deviceName = device_name;
			}
		}
	});


} catch (error) {
	error_msg = error;
};

return JSON.stringify({
	'licenses': licenses,
	'error': error_msg.toString()
});