var Azure = {
	params: {},
	token: null,

	setParams: function (params) {
		['app_id', 'password', 'tenant_id', 'subscription_id', 'resource_id'].forEach(function (field) {
			if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
				throw 'Required param is not set: ' + field + '.';
			}
		});

		Azure.params = params;
	},

	login: function () {
		var response, login = new HttpRequest();

		if (typeof Azure.params.proxy !== 'undefined' && Azure.params.proxy !== '') {
			login.setProxy(Azure.params.proxy);
		}

		login.addHeader('Content-Type: application/x-www-form-urlencoded');
		response = login.post(
			'https://login.microsoftonline.com/' + encodeURIComponent(Azure.params.tenant_id) + '/oauth2/token',
			'grant_type=client_credentials&resource=' + encodeURIComponent('https://management.azure.com/') + '&client_id=' + encodeURIComponent(Azure.params.app_id) + '&client_secret=' + encodeURIComponent(Azure.params.password)
		);

		if (login.getStatus() !== 200) {
			throw 'Login failed with status code ' + login.getStatus() + ': ' + response;
		}

		try {
			response = JSON.parse(response);
		}
		catch (error) {
			throw 'Failed to parse login session response.';
		}

		if (!response.hasOwnProperty('access_token')) {
			throw 'Authentication response does not contain access token.';
		}

		Azure.token = response['access_token'];
	},

	request: function (url) {
		var response, request = new HttpRequest();

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

		if (!Azure.token) {
			throw 'Request does not contain access token.';
		}

		request.addHeader('Content-Type: application/json');
		request.addHeader('Authorization: Bearer ' + Azure.token);
		Zabbix.log(4, '[ AzureVMSS ] request url: ' + url);

		response = request.get(url);

		if (request.getStatus() !== 200) {
			throw 'Request failed with status code ' + request.getStatus() + ': ' + response;
		}

		try {
			return JSON.parse(response);
		}
		catch (error) {
			throw 'Failed to parse response received from API.';
		}
	},

	getField: function (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;
	},

	getMetricsData: function () {
		var data = {},
			metric_endpoints = {
				'main_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('Available Memory Bytes,CPU Credits Consumed,CPU Credits Remaining,Percentage CPU,Inbound Flows,Inbound Flows Maximum Creation Rate,Network In,Network In Total,Network Out,Network Out Total,Outbound Flows,Outbound Flows Maximum Creation Rate,VmAvailabilityMetric') + '&api-version=2021-05-01&timespan=PT1M',
				'disks_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('Data Disk Bandwidth Consumed Percentage,Data Disk IOPS Consumed Percentage,Data Disk Max Burst Bandwidth,Data Disk Max Burst IOPS,Data Disk Queue Depth,Data Disk Read Bytes/sec,Data Disk Read Operations/Sec,Data Disk Target Bandwidth,Data Disk Target IOPS,Data Disk Used Burst BPS Credits Percentage,Data Disk Used Burst IO Credits Percentage,Data Disk Write Bytes/sec,Data Disk Write Operations/Sec,Disk Read Bytes,Disk Read Operations/Sec,Disk Write Bytes,Disk Write Operations/Sec') + '&api-version=2021-05-01&timespan=PT1M',
				'os_disk_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('OS Disk Bandwidth Consumed Percentage,OS Disk IOPS Consumed Percentage,OS Disk Max Burst Bandwidth,OS Disk Max Burst IOPS,OS Disk Queue Depth,OS Disk Read Bytes/sec,OS Disk Read Operations/Sec,OS Disk Target Bandwidth,OS Disk Target IOPS,OS Disk Used Burst BPS Credits Percentage,OS Disk Used Burst IO Credits Percentage,OS Disk Write Bytes/sec,OS Disk Write Operations/Sec') + '&api-version=2021-05-01&timespan=PT1M',
				'premium_and_vm_metrics': '/providers/Microsoft.Insights/metrics?metricnames=' + encodeURIComponent('Premium Data Disk Cache Read Hit,Premium Data Disk Cache Read Miss,Premium OS Disk Cache Read Hit,Premium OS Disk Cache Read Miss,VM Cached Bandwidth Consumed Percentage,VM Cached IOPS Consumed Percentage,VM Local Used Burst BPS Credits Percentage,VM Local Used Burst IO Credits Percentage,VM Remote Used Burst BPS Credits Percentage,VM Remote Used Burst IO Credits Percentage,VM Uncached Bandwidth Consumed Percentage,VM Uncached IOPS Consumed Percentage') + '&api-version=2021-05-01&timespan=PT1M'
			};

		data.metrics = {};

		Object.keys(metric_endpoints).forEach(function (field) {
			metrics = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + metric_endpoints[field]), 'value');
			for (k in metrics) {
				key = Azure.getField(metrics[k], 'name.value').replace(/(\s|\/)+/g, '');
				if (metrics[k].timeseries.length === 0) {
					metrics[k].timeseries.push({ 'data': ['nodata'] })
				}
				data.metrics[key] = Azure.getField(metrics[k], 'timeseries.0.data.0');
			}
		});

		data.capacity = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + '?api-version=2024-03-01'), 'sku.capacity');
		data.health = Azure.getField(Azure.request('https://management.azure.com' + Azure.params.resource_id + '/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01'), 'value.0.properties');

		return data
	}
};

try {
	Azure.setParams(JSON.parse(value));
	Azure.login();
	return JSON.stringify(Azure.getMetricsData());
}
catch (error) {
	error += (String(error).endsWith('.')) ? '' : '.';
	Zabbix.log(3, '[ AzureVMSS ] ERROR: ' + error);
	return JSON.stringify({ 'error': error });
}