'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.AgentUtils = undefined;

var _typeof2 = require('babel-runtime/helpers/typeof');

var _typeof3 = _interopRequireDefault(_typeof2);

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

var _regenerator2 = _interopRequireDefault(_regenerator);

var _promise = require('babel-runtime/core-js/promise');

var _promise2 = _interopRequireDefault(_promise);

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

var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);

var _stringify = require('babel-runtime/core-js/json/stringify');

var _stringify2 = _interopRequireDefault(_stringify);

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

var _keys2 = _interopRequireDefault(_keys);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

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

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

var _AgentLogger2 = _interopRequireDefault(_AgentLogger);

var _yamljs = require('yamljs');

var _yamljs2 = _interopRequireDefault(_yamljs);

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

var pullRequestData = require('./pullrequest.json');

var _require = require('url'),
    URL = _require.URL;

var crypto = require('crypto');

var log = _AgentLogger2.default.log();

var AWS = require('aws-sdk');
var proxy = require('proxy-agent');
AWS.config.update({ region: process.env.GTM_AWS_REGION });

if (process.env.IAM_ENABLED) {
    AWS.config.update({
        httpOptions: {
            agent: proxy(process.env.HTTP_PROXY)
        }
    });
} else {
    // due to serverless .env issue
    process.env.AWS_ACCESS_KEY_ID = process.env.GTM_AGENT_AWS_ACCESS_KEY_ID;
    process.env.AWS_SECRET_ACCESS_KEY = process.env.GTM_AGENT_AWS_SECRET_ACCESS_KEY;
}

var sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
var sns = new AWS.SNS({ apiVersion: '2010-03-31' });
require('babel-polyfill');
var safeJsonStringify = require('safe-json-stringify');

var AgentUtils = function () {
    function AgentUtils() {
        (0, _classCallCheck3.default)(this, AgentUtils);
    }

    (0, _createClass3.default)(AgentUtils, [{
        key: 'switchByVal',
        value: function switchByVal(cases, defaultCase, key) {
            var result = void 0;
            if (key in cases) result = cases[key];

            // if exact key not found try splitting comma delimited and check each subkey
            if (!result) {
                (0, _keys2.default)(cases).forEach(function (k) {
                    var subKeys = k.split(',').map(function (i) {
                        return i.trim();
                    });
                    if (subKeys.includes(key)) {
                        result = cases[k];
                    }
                });
            }

            if (!result) result = defaultCase;
            return result;
        }

        /**
         * Returns the URL for a Given Queue
         * @param {String} queueName - Name of Queue in Current AWS Account
         */

    }], [{
        key: 'agentId',
        value: function agentId() {
            return _AgentLogger2.default.AGENT_ID;
        }
    }, {
        key: 'sse',
        value: function sse() {
            return _AgentLogger2.default.SSE;
        }
    }, {
        key: 'stream',
        value: function stream(group, _stream) {
            _AgentLogger2.default.stream(group, _stream);
        }
    }, {
        key: 'stopStream',
        value: function stopStream(group) {
            _AgentLogger2.default.stopStream(group);
        }
    }, {
        key: 'stopAllStreams',
        value: function stopAllStreams() {
            _AgentLogger2.default.stopAllStreams();
        }
    }, {
        key: 'registerActivity',
        value: function registerActivity(ip) {
            _AgentLogger2.default.registerActivity(ip);
        }
    }, {
        key: 'samplePullRequestEvent',
        value: function samplePullRequestEvent() {
            pullRequestData.ghEventType = 'pull_request';
            return pullRequestData;
        }

        /**
         * Create a Text Mask for a String
         * @param {*} plaintext - Input String
         * @param {*} desiredLength - Length of Masked Output
         * @param {*} visibleChars - Number of Visible Characters to Show
         * @param {*} maskChar - Character to use as Mask
         */

    }, {
        key: 'maskString',
        value: function maskString() {
            var plaintext = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
            var desiredLength = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 12;
            var visibleChars = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 5;
            var maskChar = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '*';

            if (plaintext != null && plaintext.length > 0) {
                var maskLength = Math.min(plaintext.length - visibleChars, desiredLength);
                return maskChar.repeat(maskLength) + plaintext.slice(-5);
            } else {
                return '';
            }
        }

        /**
         * Create an MD5 Hash of an Input Object or String
         * @param {Object} input - Object or String to Hash
         * @param {String} salt - String for Additional Salt
         */

    }, {
        key: 'createMd5Hash',
        value: function createMd5Hash(input) {
            var salt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
            var length = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 6;

            return crypto.createHash('md5').update((0, _stringify2.default)(input) + salt).digest('hex').slice(0, length);
        }

        /**
         * Format a URL for Basic Auth
         * @param {string} username - Basic Auth Username
         * @param {string} password - Basic Auth Password
         * @param {string} url - Base URL
         */

    }, {
        key: 'formatBasicAuth',
        value: function formatBasicAuth(username, password, url) {
            var basicUrl = new URL(url);
            basicUrl.username = username;
            basicUrl.password = password;
            return basicUrl.toString();
        }

        /**
         * Create a Status Object to Send to GitHub
         * @param {object} eventData - Data from GitHub Event
         * @param {string} state - Current Task State (pending, passed, failed)
         * @param {string} context - Content Name to Display in GitHub
         * @param {string} description - Short Description to Display in GitHub
         * @param {string} url - Link to more detail
         *
         */

    }, {
        key: 'createPullRequestStatus',
        value: function createPullRequestStatus(eventData, state, context, description, url) {
            return {
                owner: eventData.repository.owner.login || 'Default_Owner',
                repo: eventData.repository.name || 'Default_Repository',
                sha: eventData.pull_request.head.sha || 'Missing SHA',
                number: eventData.pull_request.number,
                state: state,
                target_url: url ? url : 'https://github.com/zotoio/github-task-manager',
                description: description,
                context: context,
                eventData: eventData
            };
        }
    }, {
        key: 'getQueueUrl',
        value: function () {
            var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(queueName) {
                return _regenerator2.default.wrap(function _callee$(_context) {
                    while (1) {
                        switch (_context.prev = _context.next) {
                            case 0:
                                return _context.abrupt('return', sqs.getQueueUrl({ QueueName: queueName }).promise().then(function (data) {
                                    return _promise2.default.resolve(data.QueueUrl);
                                }));

                            case 1:
                            case 'end':
                                return _context.stop();
                        }
                    }
                }, _callee, this);
            }));

            function getQueueUrl(_x7) {
                return _ref.apply(this, arguments);
            }

            return getQueueUrl;
        }()

        /**
         * Update a Message Timeout on an SQS Queue
         * @param {String} queueName - Name of SQS Queue Holding Message
         * @param {String} messageHandle - Message Handle from ReceiveMessage Event
         * @param {Integer} timeoutValue - New Message Timeout Value (Seconds)
         */

    }, {
        key: 'setSqsMessageTimeout',
        value: function () {
            var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(queueName, messageHandle, timeoutValue, log) {
                return _regenerator2.default.wrap(function _callee2$(_context2) {
                    while (1) {
                        switch (_context2.prev = _context2.next) {
                            case 0:
                                log.debug('Setting SQS Message Timeout to ' + timeoutValue + ' Seconds');
                                return _context2.abrupt('return', AgentUtils.getQueueUrl(queueName).then(function (queueUrl) {
                                    log.debug('Queue URL: ' + queueUrl + ', Message Handle: ' + messageHandle + ', Timeout: ' + timeoutValue);
                                    return sqs.changeMessageVisibility({
                                        QueueUrl: queueUrl,
                                        ReceiptHandle: messageHandle,
                                        VisibilityTimeout: timeoutValue
                                    }).promise();
                                }).then(function (data) {
                                    log.debug('SQS Heartbeat Sent. (' + timeoutValue + 's) ' + (0, _stringify2.default)(data));
                                }));

                            case 2:
                            case 'end':
                                return _context2.stop();
                        }
                    }
                }, _callee2, this);
            }));

            function setSqsMessageTimeout(_x8, _x9, _x10, _x11) {
                return _ref2.apply(this, arguments);
            }

            return setSqsMessageTimeout;
        }()
    }, {
        key: 'postResultsAndTrigger',
        value: function () {
            var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(results, message, log) {
                return _regenerator2.default.wrap(function _callee3$(_context3) {
                    while (1) {
                        switch (_context3.prev = _context3.next) {
                            case 0:
                                return _context3.abrupt('return', AgentUtils.getQueueUrl(process.env.GTM_SQS_RESULTS_QUEUE).then(function (sqsQueueUrl) {
                                    var params = {
                                        MessageBody: safeJsonStringify(results),
                                        QueueUrl: sqsQueueUrl,
                                        DelaySeconds: 0
                                    };
                                    return _promise2.default.resolve(params);
                                }).then(function (params) {
                                    return sqs.sendMessage(params).promise();
                                }).then(function () {
                                    var params = {
                                        Name: process.env.GTM_SNS_RESULTS_TOPIC
                                    };

                                    return sns.createTopic(params).promise();
                                }).then(function (data) {
                                    var topicArn = data.TopicArn;
                                    var params = {
                                        Message: message,
                                        TopicArn: topicArn
                                    };
                                    return _promise2.default.resolve(params);
                                }).then(function (params) {
                                    return sns.publish(params).promise();
                                }).then(function (data) {
                                    log.info('Published Message \'' + message + '\' to Queue');
                                    log.debug(data);
                                    return _promise2.default.resolve(true);
                                }).catch(function (e) {
                                    log.error(e);
                                    throw e;
                                }));

                            case 1:
                            case 'end':
                                return _context3.stop();
                        }
                    }
                }, _callee3, this);
            }));

            function postResultsAndTrigger(_x12, _x13, _x14) {
                return _ref3.apply(this, arguments);
            }

            return postResultsAndTrigger;
        }()

        /**
         * Pause Execution for Arbitrary Time
         * @param {Integer} ms - Milliseconds to Pause
         */

    }, {
        key: 'timeout',
        value: function timeout(ms) {
            return new _promise2.default(function (resolve) {
                return setTimeout(resolve, ms);
            });
        }
    }, {
        key: 'todayDate',
        value: function todayDate() {
            var today = new Date();
            var dd = today.getDate();
            var mm = today.getMonth() + 1;
            var yyyy = today.getFullYear();
            if (dd < 10) {
                dd = '0' + dd;
            }
            if (mm < 10) {
                mm = '0' + mm;
            }
            return yyyy + '/' + mm + '/' + dd;
        }
    }, {
        key: 'logger',
        value: function logger() {
            return log;
        }
    }, {
        key: 'printBanner',
        value: function printBanner() {
            /* eslint-disable */
            var bannerData = ['_____________________  ___   _______                    _____ ', '__  ____/__  __/__   |/  /   ___    |______ ______________  /_', '_  / __ __  /  __  /|_/ /    __  /| |_  __ `/  _ \\_  __ \\  __/', '/ /_/ / _  /   _  /  / /     _  ___ |  /_/ //  __/  / / / /_  ', '\\____/  /_/    /_/  /_/      /_/  |_|\\__, / \\___//_/ /_/\\__/  ', '                                    /____/                    '];
            /* eslint-enable */
            bannerData.forEach(function (line) {
                console.log(line);
            });
        }

        /**
         * Replace Objects with Equivalent YAML Strings
         * @param {Object} optionsDict - Dictionary of Key:Value Pairs
         */

    }, {
        key: 'toYaml',
        value: function toYaml(optionsDict) {
            for (var parameter in optionsDict) {
                if (parameter.startsWith('YAML_')) {
                    var yamlString = _yamljs2.default.stringify(optionsDict[parameter], 8);
                    var varName = parameter.replace('YAML_', '');
                    optionsDict[varName] = yamlString;
                    delete optionsDict[parameter];
                } else {
                    if ((0, _typeof3.default)(optionsDict[parameter]) == 'object') {
                        optionsDict[parameter] = this.toYaml(optionsDict[parameter]);
                    }
                }
            }
            return optionsDict;
        }

        /**
         * Apply Listed Transformations to Options Dictionaries
         * @param {Object} dictionary - Dictionary of Key:Value Pairs
         */

    }, {
        key: 'applyTransforms',
        value: function applyTransforms(dictionary) {
            var transforms = {
                toYaml: this.toYaml
            };
            for (var transform in transforms) {
                dictionary = transforms[transform](dictionary);
            }
            return dictionary;
        }

        /**
         * Replace Template Strings within Objects
         * @param {Object} varDict - Source for Template Variables
         * @param {Object} template - Object to Replace Template Strings Within
         */

    }, {
        key: 'templateReplace',
        value: function templateReplace(varDict, template, log) {
            var templateStr = (0, _stringify2.default)(template);
            for (var key in varDict) {
                var re = new RegExp(key, 'g');
                log.info('Replacing ' + key + ' with ' + varDict[key]);
                templateStr = templateStr.replace(re, varDict[key]);
            }
            log.debug(templateStr);
            return JSON.parse(templateStr);
        }

        /**
         * Create a Templating Object from a Configuration Object
         * @param {Object} obj - EventData Object to Return Variables From
         */

    }, {
        key: 'createBasicTemplate',
        value: function createBasicTemplate(obj, parent, log) {
            if (!parent.results) {
                log.info('No Parent Build. Providing Safe Defaults');
                parent.results = {
                    passed: true,
                    meta: {
                        buildNumber: 0,
                        buildName: 'NO_PARENT_TASK'
                    }
                };
            }

            var mapDict = {
                '##GHPRNUM##': obj.pull_request.number,
                '##GHREPONAME##': obj.repository.name,
                '##GH_REPOSITORY_FULLNAME##': obj.repository.full_name,
                '##GH_CLONE_URL##': obj.repository.clone_url,
                '##GH_PR_BRANCHNAME##': obj.pull_request.head.ref,
                '##PARENTBUILDNUMBER##': this.metaValue(parent, 'buildNumber'),
                '##PARENTBUILDNAME##': this.metaValue(parent, 'buildName')
            };

            // just add all the GTM env vars to map
            (0, _keys2.default)(process.env).forEach(function (key) {
                if (key.startsWith('GTM_')) {
                    mapDict['##' + key + '##'] = process.env[key];
                }
            });

            return mapDict;
        }
    }, {
        key: 'metaValue',
        value: function metaValue(parent, field) {
            return parent.results.meta && parent.results.meta[field] ? parent.results.meta[field] : 'N/A';
        }
    }, {
        key: 'findMatchingElementInArray',
        value: function findMatchingElementInArray(inArray, elementToFind) {
            var foundItem = inArray.find(function (item, i) {
                if (item.$.name === elementToFind) {
                    return i;
                }
            });
            return foundItem;
        }
    }]);
    return AgentUtils;
}();

exports.AgentUtils = AgentUtils;