var base_path = 'cloudsql.googleapis.com/database/replication/',
	pgsql_path = 'cloudsql.googleapis.com/database/postgresql/replication/',
	obj = {},
	base_paths = ['network_lag', 'replica_lag', 'log_archive_failure_count', 'log_archive_success_count'];

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 "' + path + '" is not present in data received.';
		}
		data = data[step];
	}
	return data;
}

function checkParams(params) {
	['project_id', 'time_window', 'database_id', 'token'].forEach(function (field) {
		if (typeof params !== 'object' || typeof params[field] === 'undefined' || params[field] === '') {
			throw 'Required param is not set: ' + field + '.';
		}
	});
	if (!params.time_window.match(/^[0-9]+(m|h)$/)) {
		throw 'Incorrect update interval for parameter  time_window. Valid ranges 1m-23h.';
	}
	return params;
}

function getHttpData(url, token, body) {
	var request = new HttpRequest();
	if (typeof params.proxy !== 'undefined' && params.proxy !== '') {
		request.setProxy(params.proxy);
	};
	request.addHeader('Authorization: Bearer ' + token);
	request.addHeader('Content-Type: application/json');

	var response = request.post(url, JSON.stringify(body));

	if (response !== null) {
		try {
			response = JSON.parse(response);
		}
		catch (error) {
			throw 'Failed to parse response received from GCP API. Check debug log for more information.';
		}
	}

	if (typeof response !== 'object' || response === null) {
		throw 'Cannot process response data: received data is not an object. Check debug log for more information.';
	}

	if (request.getStatus() !== 200) {
		if (typeof (response.error && response.error.message) !== 'undefined') {
			throw response.error.message;
		}
		else {
			throw 'Failed to receive data: invalid response status code. Check debug log for more information.';
		}
	}
	return response;
};

var params = checkParams(JSON.parse(value)),
	filter = ' | within ' + params.time_window + " | filter database_id = '" + params.database_id + "'",
	j_filter = filter + ' | join',
	url = 'https://monitoring.googleapis.com/v3/projects/' + params.project_id + '/timeSeries:query',
	metric_raw = getHttpData(url, params.token, { query: '{' + base_paths.map(function (path) { return base_path + path; }).join(';') + '}' + j_filter }),
	metric_keys = getField(metric_raw, 'timeSeriesDescriptor.pointDescriptors'),
	metric_values = getField(metric_raw, 'timeSeriesData.0.pointData.0.values'),
	re = /(^t_\d+\.value\.)/g;

for (i in metric_keys) {
	var value_types = ['int64Value', 'doubleValue', 'stringValue', 'boolValue'];

	for (v in value_types) {
		if (typeof metric_values[i][value_types[v]] !== 'undefined') {
			obj[getField(metric_keys[i], 'key').replace(re, '')] = metric_values[i][value_types[v]];
		}
	}
}

var state_raw = getHttpData(url, params.token, { query: base_path + 'state' + filter }),
	state_keys = getField(state_raw, 'timeSeriesDescriptor.pointDescriptors'),
	state_tsd = getField(state_raw, 'timeSeriesData');

for (i in state_keys) {
	var state_key = getField(state_keys[i], 'key').replace(/value\./g, '');

	obj[state_key] = 'undefined';
	for (t in state_tsd) {
		if (getField(state_tsd[t], 'pointData.0.values.' + i + '.boolValue') == true) {
			obj[state_key] = getField(state_tsd[t], 'labelValues.3.stringValue');
			break;
		}
	}
}

var lag_raw = getHttpData(url, params.token, { query: pgsql_path + 'replica_byte_lag' + '| within ' + params.time_window + " | filter replica_name = '" + params.database_id + "'" }),
	lag_tsd = getField(lag_raw, 'timeSeriesData');

for (t in lag_tsd) {
	obj[getField(lag_tsd[t], 'labelValues.3.stringValue')] = getField(lag_tsd[t], 'pointData.0.values.0.int64Value');
}

return JSON.stringify(obj);