#!/bin/sh
':' //; exec "$(command -v nodejs || command -v node || command -v js || echo "ERROR node.js IS NOT AVAILABLE IN THIS SYSTEM")" "$0" "$@"

// shebang hack from:
// http://unix.stackexchange.com/questions/65235/universal-node-js-shebang

// Initially this is run as a shell script (#!/bin/sh).
// Then, the second line, finds nodejs or node or js in the system path
// and executes it with the shell parameters.

// --------------------------------------------------------------------------------------------------------------------

'use strict';

// --------------------------------------------------------------------------------------------------------------------
// get NETDATA environment variables

var NETDATA_PLUGINS_DIR = process.env.NETDATA_PLUGINS_DIR || __dirname;
var NETDATA_CONFIG_DIR = process.env.NETDATA_CONFIG_DIR || '/etc/netdata';
var NETDATA_UPDATE_EVERY = process.env.NETDATA_UPDATE_EVERY || 1;
var NODE_D_DIR = NETDATA_PLUGINS_DIR + '/../node.d';

// make sure the modules are found
process.mainModule.paths.unshift(NODE_D_DIR + '/node_modules');
process.mainModule.paths.unshift(NODE_D_DIR);


// --------------------------------------------------------------------------------------------------------------------
// load required modules

var fs = require('fs');
var url = require('url');
var http = require('http');
var path = require('path');
var extend = require('extend');
var netdata = require('netdata');


// --------------------------------------------------------------------------------------------------------------------
// configuration

function pluginConfig(filename) {
	var f = path.basename(filename);

	var m = f.match('.plugin' + '$');
	if(m === null) m = f.match('.node.js' + '$');
	if(m !== null)
		return netdata.options.paths.config + '/' + f.substring(0, m.index) + '.conf';

	return netdata.options.paths.config + '/' + f + '.conf';
}

// internal defaults
extend(true, netdata.options, {
	filename: path.basename(__filename),

	update_every: NETDATA_UPDATE_EVERY,

	exit_after_ms: 3600 * 4 * 1000,

	paths: {
		plugins: NETDATA_PLUGINS_DIR,
		config: NETDATA_CONFIG_DIR,
		modules: [],
	},

	modules_enable_autodetect: true,
	modules_enable_all: true,
	modules: {},
});
netdata.options.config_filename = pluginConfig(__filename);

// load configuration file
try {
	netdata.options_loaded = JSON.parse(fs.readFileSync(netdata.options.config_filename, 'utf8'));
	extend(true, netdata.options, netdata.options_loaded);
	console.error('merged netdata object:');
	console.error(netdata);
}
catch(e) {
	netdata.error('Cannot read configuration file ' + netdata.options.config_filename + ': ' + e.message + ', using internal defaults.');
	netdata.options_loaded = undefined;
	dumpError(e);
}


// apply module paths to node.js process
function applyModulePaths() {
	var len = netdata.options.paths.modules.length;
	while(len--)
		process.mainModule.paths.unshift(netdata.options.paths.modules[len]);
}
applyModulePaths();


// --------------------------------------------------------------------------------------------------------------------
// tracing

function dumpError(err) {
	if (typeof err === 'object') {
		if (err.stack) {
			netdata.debug(err.stack);
		}
	}
}

// --------------------------------------------------------------------------------------------------------------------
// get command line arguments
{
	var found_myself = false;
	var found_number = false;
	var found_modules = false;
	process.argv.forEach(function (val, index, array) {
		netdata.debug('PARAM: ' + val);

		if(!found_myself) {
			if(val === __filename)
				found_myself = true;
		}
		else {
			switch(val) {
				case 'debug':
					netdata.options.DEBUG = true;
					netdata.debug('DEBUG enabled');
					break;

				default:
					if(found_number === true) {
						if(found_modules === false) {
							for(var i in netdata.options.modules)
								netdata.options.modules[i].enabled = false;
						}

						if(typeof netdata.options.modules[val] === 'undefined')
							netdata.options.modules[val] = {};

						netdata.options.modules[val].enabled = true;
						netdata.options.modules_enable_all = false;
						netdata.debug('enabled module ' + val);
					}
					else {
						try {
							var x = parseInt(val);
							if(x > 0) {
								netdata.options.update_every = x;
								if(netdata.options.update_every < NETDATA_UPDATE_EVERY) {
									netdata.options.update_every = NETDATA_UPDATE_EVERY;
									netdata.debug('Update frequency ' + x + 's is too low');
								}

								found_number = true;
								netdata.debug('Update frequency set to ' + netdata.options.update_every + ' seconds');
							}
							else netdata.error('Ignoring parameter: ' + val);
						}
						catch(e) {
							netdata.error('Cannot get value of parameter: ' + val);
							dumpError(e);
						}
					}
					break;
			}
		}
	});
}

if(netdata.options.update_every < 1) {
	netdata.debug('Adjusting update frequency to 1 second');
	netdata.options.update_every = 1;
}

// --------------------------------------------------------------------------------------------------------------------
// find modules

function findModules() {
	var found = 0;

	var files = fs.readdirSync(NODE_D_DIR);
	var len = files.length;
	while(len--) {
		var m = files[len].match('.node.js' + '$');
		if(m !== null) {
			var n = files[len].substring(0, m.index);

			if(typeof(netdata.options.modules[n]) === 'undefined')
				netdata.options.modules[n] = { name: n, enabled: netdata.options.modules_enable_all };

			if(netdata.options.modules[n].enabled === true) {
				netdata.options.modules[n].name = n;
				netdata.options.modules[n].filename = NODE_D_DIR + '/' + files[len];
				netdata.options.modules[n].loaded = false;

				if(typeof(netdata.options.modules[n].config_filename) !== 'string')
					netdata.options.modules[n].config_filename = pluginConfig(files[len]);

				// load the module
				try {
					netdata.debug('loading module ' + netdata.options.modules[n].filename);
					netdata.options.modules[n].module = require(netdata.options.modules[n].filename);
					netdata.options.modules[n].module.name = n;
					netdata.debug('loaded module ' + netdata.options.modules[n].name + ' from ' + netdata.options.modules[n].filename);
				}
				catch(e) {
					netdata.options.modules[n].enabled = false;
					netdata.error('Cannot load module: ' + netdata.options.modules[n].filename + ' exception: ' + e);
					dumpError(e);
					continue;
				}

				// load its configuration
				var c = {
					enable_autodetect: netdata.options.modules_enable_autodetect,
					update_every: netdata.options.update_every
				};
				try {
					netdata.debug('loading module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
					var c2 = JSON.parse(fs.readFileSync(netdata.options.modules[n].config_filename, 'utf8'));
					extend(true, c, c2);
					netdata.debug('loaded module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
				}
				catch(e) {
					netdata.error('Cannot load module\'s ' + netdata.options.modules[n].name + ' config from ' + netdata.options.modules[n].config_filename + ' exception: ' + e + ', using internal defaults.');
					dumpError(e);
				}

				// call module auto-detection / configuration
				try {
					netdata.modules_configuring++;
					netdata.debug('Configuring module ' + netdata.options.modules[n].name);
					var serv = netdata.configure(netdata.options.modules[n].module, c, function() {
						netdata.debug('Configured module ' + netdata.options.modules[n].name);
						netdata.modules_configuring--;
					});

					netdata.debug('Configuring module ' + netdata.options.modules[n].name + ' reports ' + serv + ' eligible services.');
				}
				catch(e) {
					netdata.modules_configuring--;
					netdata.options.modules[n].enabled = false;
					netdata.error('Failed module auto-detection: ' + netdata.options.modules[n].name + ' exception: ' + e + ', disabling module.');
					dumpError(e);
					continue;
				}

				netdata.options.modules[n].loaded = true;
				found++;
			}
		}
	}

	// netdata.debug(netdata.options.modules);
	return found;
}

if(findModules() === 0) {
	netdata.error('Cannot load any .node.js module from: ' + NODE_D_DIR);
	netdata.disableNodePlugin();
	process.exit(1);
}


// --------------------------------------------------------------------------------------------------------------------
// start

function start_when_configuring_ends() {
	if(netdata.modules_configuring > 0) {
		netdata.debug('Waiting modules configuration, still running ' + netdata.modules_configuring);
		setTimeout(start_when_configuring_ends, 500);
		return;
	}

	netdata.modules_configuring = 0;
	netdata.start();
}
start_when_configuring_ends();

//netdata.debug('netdata object:')
//netdata.debug(netdata);
