module.exports = function (server, options) {

	// Colors for console logging
    const colors = require('ansicolors');
    const blueWazuh = colors.blue('wazuh');
	
	// Elastic JS Client
	const serverConfig = server.config();
	const elasticsearch = require('elasticsearch');
	const elasticRequest = server.plugins.elasticsearch.getCluster('data');
	
	var index_pattern = "wazuh-alerts-*";
	var index_pattern_wazuh_monitoring = "wazuh-monitoring-*";
	var index_prefix = "wazuh-alerts-";
	const fs = require('fs');
	const path = require('path');
	const KIBANA_FIELDS_FILE = '../startup/integration_files/kibana_fields_file.json';
	var kibana_fields_data = {};
		
    const payloads = {
        getFieldTop: { "size": 1, "query": { "bool": { "must": [{ "query_string": { "query": "*", "analyze_wildcard": true } }, { "range": { "@timestamp": { "gte": '', "format": "epoch_millis" } } }], "must_not": [] } }, "aggs": { "2": { "terms": { "field": '', "size": 1, "order": { "_count": "desc" } } } } },
        getLastField: { "size": 1, "query": { "bool": { "must": [{ "exists": { "field": '' } }, { "query_string": { "query": "*" } }], "must_not": [{}] } }, "sort": [{ "@timestamp": { "order": "desc", "unmapped_type": "boolean" } }] }
    };

    //Handlers

    var fetchElastic = function (req, payload) {
		return elasticRequest.callWithRequest(req, 'search', { index: 'wazuh-alerts-*', type: 'wazuh', body: payload });
    };
	
	// Returns alerts count for fields/value array between timeGTE and timeLT
    var alertsCount = function (req, reply) {
		
		var payload = {"size": 1,"query": {"bool": {"must": [], "filter": {"range": {"@timestamp": {}}}}}};
		
		// Set up time interval, default to Last 24h
        const timeGTE = req.payload.timeinterval.gte ? req.payload.timeinterval.gte : "now-1d";
        const timeLT = req.payload.timeinterval.lt ? req.payload.timeinterval.lt : "now";
		payload.query.bool.filter.range['@timestamp']["gte"] = timeGTE;
		if(timeLT != "now")
			payload.query.bool.filter.range['@timestamp']["lte"] = timeLT;
		else
			payload.query.bool.filter.range['@timestamp']["lt"] = timeLT;
		
		// Set up match for default manager name
		payload.query.bool.must.push({"match": {"manager.name": req.payload.manager}});

		// Set up match for different pairs field/value
		req.payload.fields.forEach(function(item) {
			var obj = {};
			obj[item.field] = item.value;
			payload.query.bool.must.push({"match": obj});
		})
		
		
        fetchElastic(req, payload).then(function (data) {
            reply({ 'statusCode': 200, 'data': data.hits.total });
        }, function () {
            reply({ 'statusCode': 500, 'error': 9, 'message': 'Could not get data from elasticsearch' }).code(500);
        });
    };
	
    var getFieldTop = function (req, reply) {

		// Top field payload
		var payload = {"size":1,"query":{"bool":{"must":[],"filter":{"range":{"@timestamp":{}}}}},"aggs":{"2":{"terms":{"field":"","size":1,"order":{"_count":"desc"}}}}}
		
        // Set up time interval, default to Last 24h
        const timeGTE = "now-1d";
        const timeLT = "now";
		payload.query.bool.filter.range['@timestamp']["gte"] = timeGTE;
		payload.query.bool.filter.range['@timestamp']["lt"] = timeLT;

		// Set up match for default manager name
		payload.query.bool.must.push({"match": {"manager.name": req.params.manager}});
        payload.aggs['2'].terms.field = req.params.field;

        fetchElastic(req, payload).then(function (data) {

            if (data.hits.total == 0 || typeof data.aggregations['2'].buckets[0] === 'undefined')
                reply({ 'statusCode': 200, 'data': '' });
            else
                reply({ 'statusCode': 200, 'data': data.aggregations['2'].buckets[0].key });
        }, function () {
            reply({ 'statusCode': 500, 'error': 9, 'message': 'Could not get data from elasticsearch' }).code(500);
        });
    };

    var getLastField = function (req, reply) {
        var filtering = false;
		var filterArray = {};
		var termArray = {};
		
        if (req.params.fieldValue && req.params.fieldFilter)
            filtering = true;

		var payload = JSON.parse(JSON.stringify(payloads.getLastField));
		payload.query.bool.must[0].exists.field = req.params.field;
		
		filterArray["host"]["manager.name"] = req.params.manager;
		termArray = { "term": filterArray };
		payload.query.bool.must.push(termArray);
		filterArray = {};
		termArray = {};			
			
        if (filtering) {
            filterArray[req.params.fieldFilter] = req.params.fieldValue;
            termArray = { "term": filterArray };
            payload.query.bool.must.push(termArray);	
        }
		
        fetchElastic(req, payload).then(function (data) {
			
            if (data.hits.total == 0 || typeof data.hits.hits[0] === 'undefined')
                reply({ 'statusCode': 200, 'data': '' });
            else
                reply({ 'statusCode': 200, 'data': data.hits.hits[0]._source[req.params.field] });
        }, function () {
            reply({ 'statusCode': 500, 'error': 9, 'message': 'Could not get data from elasticsearch' }).code(500);
        });
    };

	var putWazuhAlertsPattern = function (req, reply) {

		try {
			kibana_fields_data = JSON.parse(fs.readFileSync(path.resolve(__dirname, KIBANA_FIELDS_FILE), 'utf8'));
			// Get fields index pattern template  (wazuh-alerts-*)
			var wazuhAlerts_indexPattern_template = JSON.parse(kibana_fields_data.wazuh_alerts)
			var wazuhAlerts_indexPattern_current = {};
			var responseBack = {};
			var fields = [];
			for (var i = 0, len = wazuhAlerts_indexPattern_template.length; i < len; i++) {
				fields.push(wazuhAlerts_indexPattern_template[i].name);
			}

			// Get current fields index pattern (wazuh-alerts-*)
			elasticRequest.callWithInternalUser('get', { 
				index: '.kibana',
				type: 'index-pattern',
				id: index_pattern 
			}).then(
				function (response) {
					wazuhAlerts_indexPattern_current = JSON.parse(response._source.fields);
					// Compare and update fields properties
					for (var i = 0, len = wazuhAlerts_indexPattern_current.length; i < len; i++) {
						if (fields.indexOf(wazuhAlerts_indexPattern_current[i].name) >= 0) {
							wazuhAlerts_indexPattern_current[i].searchable = true;
							wazuhAlerts_indexPattern_current[i].aggregatable = true;
						}
					}
					// Update index pattern  (wazuh-alerts-*)
					elasticRequest.callWithInternalUser('update', { 
						index: '.kibana',
						type: 'index-pattern',
						id: index_pattern,
						body: {
							doc: {
								fields: JSON.stringify((wazuhAlerts_indexPattern_current))
							}
						}
					}).then(
						function (response) {
							reply({ 'response': response}).code(200);
						}, function (error) {
							reply({ 'response': error, 'error' : '1'}).code(error.statusCode);
						}
					);
				}, function (error) {
					// Create index pattern
					elasticRequest.callWithInternalUser('create', {
						index: '.kibana', 
						type: 'index-pattern', 
						id: index_pattern, 
						body: { 
							title: index_pattern, 
							timeFieldName: '@timestamp', 
							fields: kibana_fields_data.wazuh_alerts 
						} 
					}).then(
					function (response) {
							reply({ 'response': response}).code(200);
					}, function (error) {
							reply({ 'response': error, 'error' : '2'}).code(error.statusCode);
					});
				}
			);

		} catch (e) {
			  server.log([blueWazuh, 'initialize', 'error'], 'Could not read the mapping file.');
			  server.log([blueWazuh, 'initialize', 'error'], 'Path: ' + KIBANA_FIELDS_FILE);
			  server.log([blueWazuh, 'initialize', 'error'], 'Exception: ' + e);
		};
    };
	var putWazuhMonitoringPattern = function (req, reply) {
		
		try {
			kibana_fields_data = JSON.parse(fs.readFileSync(path.resolve(__dirname, KIBANA_FIELDS_FILE), 'utf8'));
			// Check if wazuh-monitoring-* exists
			elasticRequest.callWithInternalUser('get', { 
				index: '.kibana',
				type: 'index-pattern',
				id: index_pattern_wazuh_monitoring 
			}).then(
				function (response) {
					// Update index pattern  (wazuh-monitoring-*)
					elasticRequest.callWithInternalUser('update', { 
						index: '.kibana',
						type: 'index-pattern',
						id: index_pattern_wazuh_monitoring,
						body: {
							doc: {
								fields: kibana_fields_data.wazuh_monitoring
							}
						}
					}).then(
						function (response) {
							reply({ 'response': response}).code(200);
						}, function (error) {
							reply({ 'response': error }).code(error.statusCode);
						}
					);
				}, function (error) {
					// Create index pattern
					elasticRequest.callWithInternalUser('create', {
						index: '.kibana', 
						type: 'index-pattern', 
						id: index_pattern_wazuh_monitoring, 
						body: { 
							title: index_pattern_wazuh_monitoring, 
							timeFieldName: '@timestamp', 
							fields: kibana_fields_data.wazuh_monitoring 
						} 
					}).then(
					function (response) {
							reply({ 'response': response}).code(200);
					}, function (error) {
							reply({ 'response': error, 'error' : '2'}).code(error.statusCode);
					});			
				}
			);
		} catch (e) {
			  server.log([blueWazuh, 'initialize', 'error'], 'Could not read the mapping file.');
			  server.log([blueWazuh, 'initialize', 'error'], 'Path: ' + KIBANA_FIELDS_FILE);
			  server.log([blueWazuh, 'initialize', 'error'], 'Exception: ' + e);
		};	
	}
	
    //Server routes 

    /*
    * GET /api/wazuh-elastic/top/{manager}/{field}/{time?}
    * Returns the agent with most alerts
    *
    **/
    server.route({
        method: 'GET',
        path: '/api/wazuh-elastic/top/{manager}/{field}/{time?}',
        handler: getFieldTop
    });

	/*
    * GET /api/wazuh-elastic/top/{manager}/{field}/{fieldFilter}/{fieldValue}/{time?}
    * Returns the agent with most alerts
    *
    **/
    server.route({
        method: 'GET',
        path: '/api/wazuh-elastic/top/{manager}/{field}/{fieldFilter}/{fieldValue}/{time?}',
        handler: getFieldTop
    });
	
	/*
    * GET /api/wazuh-elastic/top/{manager}/{field}/{fieldFilter}/{fieldValue}/{fieldFilter}/{fieldValue}/{time?}
    * Returns the agent with most alerts
    *
    **/
    server.route({
        method: 'GET',
        path: '/api/wazuh-elastic/top/{manager}/{field}/{fieldFilter}/{fieldValue}/{fieldFilter2}/{fieldValue2}/{time?}',
        handler: getFieldTop
    });
	
	/*
    * /api/wazuh-elastic/alerts-count
    * Returns alerts count for fields/value array between timeGTE and timeLT
    * @params: fields[{field,value}], manager, timeinterval{gte,lte}
    **/
    server.route({
        method: 'POST',
        path: '/api/wazuh-elastic/alerts-count/',
        handler: alertsCount
    });		
    /*
    * GET /api/wazuh-elastic/last/{manager}/{field}
    * Return last field value
    *
    **/
    server.route({
        method: 'GET',
        path: '/api/wazuh-elastic/last/{manager}/{field}',
        handler: getLastField
    });
    /*
	
	/*
    * GET /api/wazuh-elastic/last/{manager}/{field}/{fieldFilter}/{fieldValue}
    * Return last field value
    *
    **/
    server.route({
        method: 'GET',
        path: '/api/wazuh-elastic/last/{manager}/{field}/{fieldFilter}/{fieldValue}',
        handler: getLastField
    });
	
	/*
    * PUT /api/wazuh-elastic/wazuh-pattern
    * Set wazuh index pattern
    *
    **/
    server.route({
        method: 'PUT',
        path: '/api/wazuh-elastic/wazuh-alerts-pattern',
        handler: putWazuhAlertsPattern
    });
	
	/*
    * PUT /api/wazuh-elastic/wazuh-pattern
    * Set wazuh index pattern
    *
    **/
    server.route({
        method: 'PUT',
        path: '/api/wazuh-elastic/wazuh-monitoring-pattern',
        handler: putWazuhMonitoringPattern
    });	
};