'use strict';

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

var _keys2 = _interopRequireDefault(_keys);

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

var _bunyan = require('bunyan');

var _bunyan2 = _interopRequireDefault(_bunyan);

var _bunyanFormat = require('bunyan-format');

var _bunyanFormat2 = _interopRequireDefault(_bunyanFormat);

var _cwlogsWritable = require('cwlogs-writable');

var _cwlogsWritable2 = _interopRequireDefault(_cwlogsWritable);

var _v = require('uuid/v4');

var _v2 = _interopRequireDefault(_v);

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

var _expressSse2 = _interopRequireDefault(_expressSse);

var _proxyAgent = require('proxy-agent');

var _proxyAgent2 = _interopRequireDefault(_proxyAgent);

var _bunyanLogstashTcp = require('bunyan-logstash-tcp');

var _bunyanLogstashTcp2 = _interopRequireDefault(_bunyanLogstashTcp);

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

var SSE = [];
var AGENT_ID = (0, _v2.default)();
var STREAM = [];
var LOG = process.env.NODE_ENV === 'test' ? console : create(AGENT_ID);
var STREAM_USER_LAST_ACTIVITY = Date.now();

var logGroupMap = [];
logGroupMap['gtmGithubHook'] = '/aws/lambda/gtmGithubHook-dev-gtmGithubHook';
logGroupMap['gtmGithubResults'] = '/aws/lambda/gtmGithubHook-dev-gtmGithubResults';
logGroupMap[process.env.GTM_AGENT_CLOUDWATCH_LOGS_GROUP] = process.env.GTM_AGENT_CLOUDWATCH_LOGS_GROUP;

var CWLogFilterEventStream = require('smoketail').CWLogFilterEventStream;
var janitorInterval = void 0;

function create(agentId) {
    if (!agentId) console.warn('agentId is not set.');

    var CWLogOptions = {
        region: process.env.GTM_AWS_REGION
    };

    if (process.env.IAM_ENABLED) {
        CWLogOptions = {
            region: process.env.GTM_AWS_REGION,
            //accessKeyId: process.env.AWS_ACCESS_KEY_ID,
            //secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
            //sessionToken: process.env.AWS_SECURITY_TOKEN,
            httpOptions: {
                agent: (0, _proxyAgent2.default)(process.env.HTTP_PROXY)
            }
        };
    }

    var cloudWatchStream = new _cwlogsWritable2.default({
        logGroupName: process.env.GTM_AGENT_CLOUDWATCH_LOGS_GROUP || 'gtmAgent',
        logStreamName: 'AGENT_ID=' + agentId,
        cloudWatchLogsOptions: CWLogOptions
    }).on('error', console.error);

    janitorInterval = setInterval(streamJanitor, 60000);

    var bunyanConf = {
        name: agentId.substring(0, 7),
        streams: [{
            stream: cloudWatchStream,
            type: 'raw'
        }, {
            stream: (0, _bunyanFormat2.default)({ outputMode: 'short' })
        }]
    };

    if (process.env.GTM_LOGSTASH_HOST) {
        var logstashPort = process.env.GTM_LOGSTASH_PORT || 5000;

        bunyanConf.streams.push({
            type: 'raw',
            stream: _bunyanLogstashTcp2.default.createStream({
                host: process.env.GTM_LOGSTASH_HOST,
                port: logstashPort
            }).on('error', console.error)
        });
    }

    return _bunyan2.default.createLogger(bunyanConf);
}

function log() {
    return LOG;
}

// important - do not use log() in this function, or a cloudwatch loop will occur :)
function stream(groupName, streamName) {
    console.log('starting cloudwatch stream (groupName: ' + groupName + ', streamName: ' + (streamName || 'ALL') + ')');

    if (!SSE[groupName]) {
        SSE[groupName] = new _expressSse2.default();
    }

    var filterOpts = {
        logGroupName: logGroupMap[groupName],
        logStreamNames: streamName && streamName !== 'ALL' ? [streamName] : undefined,
        startTime: Date.now(),
        follow: true,
        followInterval: 5000
    };

    var awsOpts = {
        region: process.env.GTM_AWS_REGION
    };

    if (STREAM[groupName]) {
        stopStream(groupName);
    }

    STREAM[groupName] = new CWLogFilterEventStream(filterOpts, awsOpts);

    STREAM[groupName].on('error', function (err) {
        console.log(err);
    });

    STREAM[groupName].on('end', function () {
        console.log(groupName + ' stream closed');
    });

    STREAM[groupName].on('data', function (eventObject) {
        /*console.debug( // noisy!
            'Timestamp: ', new Date(eventObject.timestamp),
            'Message: ', eventObject.message
        );*/

        if (SSE[groupName]) {
            SSE[groupName].send(eventObject);
        }
    });
}

function stopAllStreams() {
    (0, _keys2.default)(STREAM).forEach(function (group) {
        stopStream(group);
    });
}

function stopStream(group) {
    if (STREAM[group]) {
        console.log('closing stream: ' + group);
        STREAM[group].close();
        STREAM[group] = null;
    }
}

function registerActivity(ip) {
    STREAM_USER_LAST_ACTIVITY = Date.now();
    log().debug('stream keepalive request from ' + ip + '..');
}

function streamJanitor() {
    var maxMinutesInactivity = 2;
    //console.log(`streamJanitor ${Date.now()}, ${STREAM_USER_LAST_ACTIVITY}`);
    if ((0, _keys2.default)(STREAM).length > 0 && Date.now() - STREAM_USER_LAST_ACTIVITY > maxMinutesInactivity * 60 * 1000) {
        log().info('closing streams after no browsers detected for ' + maxMinutesInactivity + ' minutes.');
        stopAllStreams();
        clearInterval(janitorInterval);
    }
}

module.exports = {
    log: log,
    stream: stream,
    stopStream: stopStream,
    stopAllStreams: stopAllStreams,
    registerActivity: registerActivity,
    AGENT_ID: AGENT_ID,
    SSE: SSE
};