'use strict';

var _keys = require('babel-runtime/core-js/object/keys');

var _keys2 = _interopRequireDefault(_keys);

var _regenerator = require('babel-runtime/regenerator');

var _regenerator2 = _interopRequireDefault(_regenerator);

var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');

var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);

var configureRoutes = function () {
    var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee12(app) {
        var _this = this;

        var getEventLogs = function () {
            var _ref5 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee4(ghEventId) {
                var results;
                return _regenerator2.default.wrap(function _callee4$(_context4) {
                    while (1) {
                        switch (_context4.prev = _context4.next) {
                            case 0:
                                _context4.next = 2;
                                return elastic.search({
                                    index: 'logstash*',
                                    size: 1000,
                                    body: {
                                        query: {
                                            match: {
                                                ghEventId: ghEventId
                                            }
                                        }
                                    },
                                    sort: '@timestamp:asc'
                                });

                            case 2:
                                results = _context4.sent;
                                return _context4.abrupt('return', results.hits.hits);

                            case 4:
                            case 'end':
                                return _context4.stop();
                        }
                    }
                }, _callee4, this);
            }));

            return function getEventLogs(_x7) {
                return _ref5.apply(this, arguments);
            };
        }();

        var getHealth = function () {
            var _ref8 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee7(includeDetails) {
                return _regenerator2.default.wrap(function _callee7$(_context7) {
                    while (1) {
                        switch (_context7.prev = _context7.next) {
                            case 0:
                                _context7.t0 = getAgentInfo(includeDetails);
                                _context7.t1 = getProcessInfo(includeDetails);
                                _context7.next = 4;
                                return getElasticInfo(includeDetails);

                            case 4:
                                _context7.t2 = _context7.sent;
                                _context7.next = 7;
                                return getDynamoInfo(includeDetails);

                            case 7:
                                _context7.t3 = _context7.sent;
                                _context7.next = 10;
                                return getSQSInfo(includeDetails);

                            case 10:
                                _context7.t4 = _context7.sent;
                                return _context7.abrupt('return', {
                                    agent: _context7.t0,
                                    node: _context7.t1,
                                    elastic: _context7.t2,
                                    dynamodb: _context7.t3,
                                    sqs: _context7.t4
                                });

                            case 12:
                            case 'end':
                                return _context7.stop();
                        }
                    }
                }, _callee7, this);
            }));

            return function getHealth(_x12) {
                return _ref8.apply(this, arguments);
            };
        }();

        var getElasticInfo = function () {
            var _ref9 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee8(includeDetails) {
                var result;
                return _regenerator2.default.wrap(function _callee8$(_context8) {
                    while (1) {
                        switch (_context8.prev = _context8.next) {
                            case 0:
                                result = 'not configured';

                                if (!(process.env.GTM_ELASTIC_HOST && process.env.GTM_ELASTIC_PORT)) {
                                    _context8.next = 6;
                                    break;
                                }

                                _context8.next = 4;
                                return (0, _requestPromiseNative2.default)({
                                    json: true,
                                    uri: 'http://' + process.env.GTM_ELASTIC_HOST + ':' + process.env.GTM_ELASTIC_PORT
                                });

                            case 4:
                                result = _context8.sent;

                                if (!includeDetails) {
                                    result = 'found';
                                }

                            case 6:
                                return _context8.abrupt('return', result);

                            case 7:
                            case 'end':
                                return _context8.stop();
                        }
                    }
                }, _callee8, this);
            }));

            return function getElasticInfo(_x13) {
                return _ref9.apply(this, arguments);
            };
        }();

        var getSQSInfo = function () {
            var _ref10 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee9(includeDetails) {
                var sqsPendingStats, sqsResultsStats;
                return _regenerator2.default.wrap(function _callee9$(_context9) {
                    while (1) {
                        switch (_context9.prev = _context9.next) {
                            case 0:
                                _context9.next = 2;
                                return describeQueue(process.env.GTM_SQS_PENDING_QUEUE, ['All'], true);

                            case 2:
                                sqsPendingStats = _context9.sent;
                                _context9.next = 5;
                                return describeQueue(process.env.GTM_SQS_RESULTS_QUEUE, ['All'], true);

                            case 5:
                                sqsResultsStats = _context9.sent;

                                if (!includeDetails) {
                                    sqsPendingStats = 'found';
                                    sqsResultsStats = 'found';
                                }
                                return _context9.abrupt('return', {
                                    pending: sqsPendingStats,
                                    results: sqsResultsStats
                                });

                            case 8:
                            case 'end':
                                return _context9.stop();
                        }
                    }
                }, _callee9, this);
            }));

            return function getSQSInfo(_x14) {
                return _ref10.apply(this, arguments);
            };
        }();

        var getDynamoInfo = function () {
            var _ref11 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee10(includeDetails) {
                var result;
                return _regenerator2.default.wrap(function _callee10$(_context10) {
                    while (1) {
                        switch (_context10.prev = _context10.next) {
                            case 0:
                                result = 'not configured';

                                if (!EVENTS_TABLE) {
                                    _context10.next = 7;
                                    break;
                                }

                                _context10.next = 4;
                                return ddb.describeTable({ TableName: EVENTS_TABLE }).promise();

                            case 4:
                                _context10.t0 = _context10.sent;
                                result = {
                                    events: _context10.t0
                                };

                                if (!includeDetails) {
                                    result = 'found';
                                }

                            case 7:
                                return _context10.abrupt('return', result);

                            case 8:
                            case 'end':
                                return _context10.stop();
                        }
                    }
                }, _callee10, this);
            }));

            return function getDynamoInfo(_x15) {
                return _ref11.apply(this, arguments);
            };
        }();

        var describeQueue = function () {
            var _ref12 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee11(queueName, attributeNameArray, includeDetails) {
                var sqs, queueUrl, sqsQueueParams, queueDetails, result;
                return _regenerator2.default.wrap(function _callee11$(_context11) {
                    while (1) {
                        switch (_context11.prev = _context11.next) {
                            case 0:
                                sqs = new _awsSdk2.default.SQS();

                                if (includeDetails) {
                                    _context11.next = 3;
                                    break;
                                }

                                return _context11.abrupt('return', 'found');

                            case 3:
                                _context11.next = 5;
                                return sqs.getQueueUrl({ QueueName: queueName }).promise();

                            case 5:
                                queueUrl = _context11.sent;

                                log.debug('sqs queue url ' + queueName + ': ' + _formatJson2.default.plain(queueUrl));
                                if (!attributeNameArray) attributeNameArray = ['All'];
                                sqsQueueParams = {
                                    QueueUrl: queueUrl.QueueUrl,
                                    AttributeNames: attributeNameArray
                                };
                                _context11.next = 11;
                                return sqs.getQueueAttributes(sqsQueueParams).promise();

                            case 11:
                                queueDetails = _context11.sent;
                                result = {};

                                result.name = queueName;
                                result.url = queueUrl.QueueUrl;
                                result.attributes = queueDetails.Attributes;
                                log.debug('sqs queue details: ' + result);
                                return _context11.abrupt('return', result);

                            case 18:
                            case 'end':
                                return _context11.stop();
                        }
                    }
                }, _callee11, this);
            }));

            return function describeQueue(_x16, _x17, _x18) {
                return _ref12.apply(this, arguments);
            };
        }();

        var ddb, ddbDocClient, tableDetails, tableStreamArn, ddbStream, getAgentInfo, getProcessInfo, getEnvParams;
        return _regenerator2.default.wrap(function _callee12$(_context12) {
            while (1) {
                switch (_context12.prev = _context12.next) {
                    case 0:
                        getEnvParams = function getEnvParams() {
                            var env = {};
                            (0, _keys2.default)(process.env).sort().forEach(function (key) {
                                if (key.startsWith('GTM')) {
                                    env[key] = _AgentUtils.AgentUtils.varMask(key, process.env[key]);
                                }
                            });
                            return env;
                        };

                        getProcessInfo = function getProcessInfo() {
                            return {
                                version: process.version,
                                pid: process.pid,
                                uptime: process.uptime(),
                                cpuUsage: process.cpuUsage(),
                                memoryUsage: process.memoryUsage()
                            };
                        };

                        getAgentInfo = function getAgentInfo(includeDetails) {
                            var result = {
                                id: _AgentUtils.AgentUtils.agentId(),
                                version: _package.version,
                                group: agentGroup
                            };
                            if (includeDetails) {
                                result.env = getEnvParams();
                            }
                            return result;
                        };

                        ddb = new _awsSdk2.default.DynamoDB();
                        ddbDocClient = new _awsSdk2.default.DynamoDB.DocumentClient({
                            convertEmptyValues: true
                        });
                        _context12.next = 7;
                        return ddb.describeTable({ TableName: EVENTS_TABLE }).promise();

                    case 7:
                        tableDetails = _context12.sent;

                        log.debug(_formatJson2.default.plain(tableDetails));
                        tableStreamArn = tableDetails.Table.LatestStreamArn;
                        ddbStream = new _dynamodbStream2.default(new _awsSdk2.default.DynamoDBStreams(), tableStreamArn);


                        ddbStream.on('error', function (err) {
                            log.error(err);
                        });

                        ddbStream.on('end', function () {
                            log.info('stream closed');
                        });

                        // fetch stream state initially
                        ddbStream.fetchStreamState(function () {
                            var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(err) {
                                var eventData;
                                return _regenerator2.default.wrap(function _callee$(_context) {
                                    while (1) {
                                        switch (_context.prev = _context.next) {
                                            case 0:
                                                if (!err) {
                                                    _context.next = 3;
                                                    break;
                                                }

                                                log.error(err);
                                                return _context.abrupt('return', process.exit(1));

                                            case 3:
                                                _context.next = 5;
                                                return ddbDocClient.scan({ TableName: EVENTS_TABLE }).promise();

                                            case 5:
                                                eventData = _context.sent;

                                                INITIAL_DATA = eventData.Items;
                                                log.debug('INITIAL_DATA: ' + _formatJson2.default.plain(INITIAL_DATA));

                                                // poll
                                                (0, _tempusFugit.schedule)({ second: 10 }, function (job) {
                                                    ddbStream.fetchStreamState(job.callback());
                                                });

                                                EventMetricStream = new _expressSse2.default(INITIAL_DATA);
                                                app.get('/metrics/stream', EventMetricStream.init);

                                                app.get('/metrics', function (req, res) {
                                                    res.render('metrics.html');
                                                });

                                            case 12:
                                            case 'end':
                                                return _context.stop();
                                        }
                                    }
                                }, _callee, _this);
                            }));

                            return function (_x2) {
                                return _ref2.apply(this, arguments);
                            };
                        }());

                        app.get('/metrics/log/gtm-:ghEventId.txt', function () {
                            var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(req, res) {
                                var ghEventId, logs;
                                return _regenerator2.default.wrap(function _callee2$(_context2) {
                                    while (1) {
                                        switch (_context2.prev = _context2.next) {
                                            case 0:
                                                if (elastic) {
                                                    _context2.next = 4;
                                                    break;
                                                }

                                                res.write('elasticsearch is not configured');
                                                res.end();
                                                return _context2.abrupt('return');

                                            case 4:
                                                ghEventId = req.params.ghEventId;
                                                _context2.next = 7;
                                                return getEventLogs(ghEventId);

                                            case 7:
                                                logs = _context2.sent;


                                                logs.forEach(function (log) {
                                                    res.write(log._source['@timestamp'] + ' ' + log._source.message + ' \n');
                                                });

                                                res.end();

                                            case 10:
                                            case 'end':
                                                return _context2.stop();
                                        }
                                    }
                                }, _callee2, _this);
                            }));

                            return function (_x3, _x4) {
                                return _ref3.apply(this, arguments);
                            };
                        }());

                        app.get('/metrics/log/gtm-:ghEventId.json', function () {
                            var _ref4 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(req, res) {
                                var ghEventId, logs;
                                return _regenerator2.default.wrap(function _callee3$(_context3) {
                                    while (1) {
                                        switch (_context3.prev = _context3.next) {
                                            case 0:
                                                if (elastic) {
                                                    _context3.next = 4;
                                                    break;
                                                }

                                                res.json({ error: 'elasticsearch is not configured' });
                                                res.end();
                                                return _context3.abrupt('return');

                                            case 4:
                                                ghEventId = req.params.ghEventId;
                                                _context3.next = 7;
                                                return getEventLogs(ghEventId);

                                            case 7:
                                                logs = _context3.sent;

                                                res.json(logs);

                                            case 9:
                                            case 'end':
                                                return _context3.stop();
                                        }
                                    }
                                }, _callee3, _this);
                            }));

                            return function (_x5, _x6) {
                                return _ref4.apply(this, arguments);
                            };
                        }());

                        ddbStream.on('insert record', function (eventObject) {
                            log.debug('inserted ' + _formatJson2.default.plain(eventObject));
                            INITIAL_DATA.push(eventObject);
                            EventMetricStream.updateInit(INITIAL_DATA);
                            EventMetricStream.send(eventObject);
                        });

                        ddbStream.on('modify record', function (eventObject) {
                            log.debug('updated ' + _formatJson2.default.plain(eventObject));
                            INITIAL_DATA.push(eventObject);
                            EventMetricStream.updateInit(INITIAL_DATA);
                            EventMetricStream.send(eventObject);
                        });

                        app.get('/metrics/health', function () {
                            var _ref6 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee5(req, res) {
                                var includeDetail, result;
                                return _regenerator2.default.wrap(function _callee5$(_context5) {
                                    while (1) {
                                        switch (_context5.prev = _context5.next) {
                                            case 0:
                                                includeDetail = false;
                                                _context5.next = 3;
                                                return getHealth(includeDetail);

                                            case 3:
                                                result = _context5.sent;

                                                res.json(result);
                                                res.end();

                                            case 6:
                                            case 'end':
                                                return _context5.stop();
                                        }
                                    }
                                }, _callee5, _this);
                            }));

                            return function (_x8, _x9) {
                                return _ref6.apply(this, arguments);
                            };
                        }());

                        app.get('/metrics/health/detail', function () {
                            var _ref7 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee6(req, res) {
                                var includeDetail, result;
                                return _regenerator2.default.wrap(function _callee6$(_context6) {
                                    while (1) {
                                        switch (_context6.prev = _context6.next) {
                                            case 0:
                                                includeDetail = true;
                                                _context6.next = 3;
                                                return getHealth(includeDetail);

                                            case 3:
                                                result = _context6.sent;

                                                res.json(result);
                                                res.end();

                                            case 6:
                                            case 'end':
                                                return _context6.stop();
                                        }
                                    }
                                }, _callee6, _this);
                            }));

                            return function (_x10, _x11) {
                                return _ref7.apply(this, arguments);
                            };
                        }());

                    case 20:
                    case 'end':
                        return _context12.stop();
                }
            }
        }, _callee12, this);
    }));

    return function configureRoutes(_x) {
        return _ref.apply(this, arguments);
    };
}();

require('source-map-support/register');

var _expressSse = require('express-sse');

var _expressSse2 = _interopRequireDefault(_expressSse);

var _awsSdk = require('aws-sdk');

var _awsSdk2 = _interopRequireDefault(_awsSdk);

var _AgentLogger = require('./AgentLogger');

var _AgentLogger2 = _interopRequireDefault(_AgentLogger);

var _formatJson = require('format-json');

var _formatJson2 = _interopRequireDefault(_formatJson);

var _dynamodbStream = require('dynamodb-stream');

var _dynamodbStream2 = _interopRequireDefault(_dynamodbStream);

var _elasticsearch = require('elasticsearch');

var _elasticsearch2 = _interopRequireDefault(_elasticsearch);

var _tempusFugit = require('tempus-fugit');

var _AgentUtils = require('./AgentUtils');

var _requestPromiseNative = require('request-promise-native');

var _requestPromiseNative2 = _interopRequireDefault(_requestPromiseNative);

var _package = require('../../../package.json');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var agentGroup = process.env.GTM_AGENT_GROUP || 'default';

_awsSdk2.default.config.update({ region: process.env.GTM_AWS_REGION });

var log = _AgentLogger2.default.log();
var EVENTS_TABLE = process.env.GTM_DYNAMO_TABLE_EVENTS;
var INITIAL_DATA = [];
var EventMetricStream = void 0;

var elastic = void 0;
if (process.env.GTM_ELASTIC_HOST && process.env.GTM_ELASTIC_PORT) {
    elastic = new _elasticsearch2.default.Client({
        host: process.env.GTM_ELASTIC_HOST + ':' + process.env.GTM_ELASTIC_PORT,
        log: 'info'
    });
}

module.exports = {
    configureRoutes: configureRoutes
};