'use strict';

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

var _values = require('babel-runtime/core-js/object/values');

var _values2 = _interopRequireDefault(_values);

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 _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');

var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);

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

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

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

var _createClass3 = _interopRequireDefault(_createClass2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

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

var _teamcityRestApi = require('teamcity-rest-api');

var _teamcityRestApi2 = _interopRequireDefault(_teamcityRestApi);

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

var _requestPromiseNative2 = _interopRequireDefault(_requestPromiseNative);

var _jsontoxml = require('jsontoxml');

var _jsontoxml2 = _interopRequireDefault(_jsontoxml);

var _xml2js = require('xml2js');

var _xml2js2 = _interopRequireDefault(_xml2js);

var _url = require('url');

var _url2 = _interopRequireDefault(_url);

var _Executor2 = require('../agent/Executor');

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

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

/**
 * Sample .githubTaskManager.json task config
 *
 * see: https://github.com/zotoio/github-task-manager/wiki/Structure-of-.githubTaskManager.json
 *
 * {
        "executor": "TeamCity",
        "context": "run e2e tests",
        "options": {
          "jobName": "projectName_id",
          "parameters": {
            "build_tag" : "proj_wasX",
            "ENVIRONMENT" : "env_dev",
            "cuke_env" : "env_dev|staging|prod",
            "cuke_tags" : [
              "@proj_wasX",
              "@proj_wasn"
            ]
          }
        }
    }
*/

var ExecutorTeamCity = exports.ExecutorTeamCity = function (_Executor) {
    (0, _inherits3.default)(ExecutorTeamCity, _Executor);

    function ExecutorTeamCity(eventData, log) {
        (0, _classCallCheck3.default)(this, ExecutorTeamCity);

        var _this = (0, _possibleConstructorReturn3.default)(this, (ExecutorTeamCity.__proto__ || (0, _getPrototypeOf2.default)(ExecutorTeamCity)).call(this, eventData, log));

        _this.log = log;
        _this.options = _this.getOptions();

        _this.teamCity = _teamcityRestApi2.default.create({
            url: _this.options.GTM_TEAMCITY_URL,
            username: _this.options.GTM_TEAMCITY_USER,
            password: _this.options.GTM_TEAMCITY_PASSCODE
        });
        return _this;
    }

    (0, _createClass3.default)(ExecutorTeamCity, [{
        key: 'createTeamCityBuildNode',
        value: function createTeamCityBuildNode(task, jobName) {
            var xml = void 0;
            var xmlNode = {
                name: 'build',
                attrs: {},
                children: [{ name: 'buildType', attrs: { id: jobName } }, { name: 'properties', children: [] }]
            };

            if (task.options.hasOwnProperty('branchName')) {
                xmlNode.attrs.branchName = task.options.branchName;
            }

            for (var buildProperty in task.options.parameters) {
                var property = {
                    name: 'property',
                    attrs: {
                        name: buildProperty,
                        value: task.options.parameters[buildProperty]
                    }
                };
                xmlNode.children[1].children.push(property);
            }

            xml = (0, _jsontoxml2.default)([xmlNode]);
            return xml;
        }
    }, {
        key: 'executeTask',
        value: function () {
            var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(task) {
                var log, jobName, buildNode, teamCityBuildId, completedBuild, result, overAllResult, statisticsUrl, statistics, parsedResult;
                return _regenerator2.default.wrap(function _callee$(_context) {
                    while (1) {
                        switch (_context.prev = _context.next) {
                            case 0:
                                log = this.log;
                                jobName = task.options.jobName;

                                if (!(jobName == undefined)) {
                                    _context.next = 6;
                                    break;
                                }

                                _context.next = 5;
                                return _AgentUtils.AgentUtils.timeout(4000);

                            case 5:
                                return _context.abrupt('return', 'NO_MATCHING_TASK');

                            case 6:
                                buildNode = this.createTeamCityBuildNode(task, jobName);
                                _context.next = 9;
                                return this.teamCity.builds.startBuild(buildNode);

                            case 9:
                                teamCityBuildId = _context.sent;

                                log.info('TeamCity Project[' + jobName + '] with buildNumber : ' + teamCityBuildId.id + ' Started.');

                                _context.next = 13;
                                return this.waitForBuildToComplete(jobName, teamCityBuildId.id);

                            case 13:
                                completedBuild = _context.sent;

                                log.info('TeamCity Project[' + jobName + '] with buildNumber : #' + teamCityBuildId.id + ' finished with status : ' + completedBuild.status);

                                result = completedBuild.status === 'SUCCESS';
                                overAllResult = { passed: result, url: completedBuild.buildType.webUrl };

                                if (!task.options.parameters.hasOwnProperty('cuke_tags')) {
                                    _context.next = 25;
                                    break;
                                }

                                statisticsUrl = _AgentUtils.AgentUtils.formatBasicAuth(this.options.GTM_TEAMCITY_USER, this.options.GTM_TEAMCITY_PASSCODE, _url2.default.resolve(this.options.GTM_TEAMCITY_URL, '/app/rest/builds/id:' + teamCityBuildId.id + '/statistics'));
                                _context.next = 21;
                                return this.getBuildStatistics(statisticsUrl);

                            case 21:
                                statistics = _context.sent;
                                parsedResult = this.createResultObject(statistics);

                                parsedResult.testResultsUrl = _url2.default.resolve(this.options.GTM_TEAMCITY_URL, '/viewLog.html?buildId=' + teamCityBuildId.id + '&tab=buildResultsDiv&buildTypeId=' + teamCityBuildId.id);

                                overAllResult.message = parsedResult;

                            case 25:

                                task.results = overAllResult;

                                return _context.abrupt('return', result ? _promise2.default.resolve(task) : _promise2.default.reject(task));

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

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

            return executeTask;
        }()
    }, {
        key: 'waitForBuildToComplete',
        value: function () {
            var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(buildName, buildNumber) {
                var log, buildDict, maxRetries, tries;
                return _regenerator2.default.wrap(function _callee2$(_context2) {
                    while (1) {
                        switch (_context2.prev = _context2.next) {
                            case 0:
                                log = this.log;
                                _context2.next = 3;
                                return this.teamCity.builds.get(buildNumber);

                            case 3:
                                buildDict = _context2.sent;
                                maxRetries = 600;
                                tries = 1;

                            case 6:
                                if (!(buildDict.state !== 'finished' && tries++ < maxRetries)) {
                                    _context2.next = 14;
                                    break;
                                }

                                _context2.next = 9;
                                return _AgentUtils.AgentUtils.timeout(5000);

                            case 9:
                                _context2.next = 11;
                                return this.teamCity.builds.get(buildNumber).then(function (data) {
                                    log.debug('Waiting for Build \'' + buildName + '\' to Finish: ' + tries);
                                    return data;
                                });

                            case 11:
                                buildDict = _context2.sent;
                                _context2.next = 6;
                                break;

                            case 14:
                                log.debug('TeamCity Project[' + buildName + '] with buildNumber : #' + buildNumber + ' : ' + buildDict.state);
                                return _context2.abrupt('return', buildDict);

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

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

            return waitForBuildToComplete;
        }()
    }, {
        key: 'getBuildStatistics',
        value: function () {
            var _ref3 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee3(statisticsUrl) {
                var log, tries, maxRetries, resultData;
                return _regenerator2.default.wrap(function _callee3$(_context3) {
                    while (1) {
                        switch (_context3.prev = _context3.next) {
                            case 0:
                                log = this.log;

                                log.debug('Starting http request.. : ' + statisticsUrl);

                                tries = 1;
                                maxRetries = 100;
                                resultData = void 0;
                                _context3.next = 7;
                                return (0, _requestPromiseNative2.default)(statisticsUrl);

                            case 7:
                                resultData = _context3.sent;

                            case 8:
                                if (!(!resultData.includes('SuccessRate') && tries++ < maxRetries)) {
                                    _context3.next = 16;
                                    break;
                                }

                                _context3.next = 11;
                                return _AgentUtils.AgentUtils.timeout(3000);

                            case 11:
                                _context3.next = 13;
                                return (0, _requestPromiseNative2.default)(statisticsUrl).then(function (data) {
                                    return data;
                                });

                            case 13:
                                resultData = _context3.sent;
                                _context3.next = 8;
                                break;

                            case 16:
                                return _context3.abrupt('return', resultData);

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

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

            return getBuildStatistics;
        }()
    }, {
        key: 'createResultObject',
        value: function createResultObject(statistics) {
            var resultObject = {};

            var parsedJSON = void 0;
            var parser = new _xml2js2.default.Parser();
            parser.parseString(statistics, function (err, result) {
                parsedJSON = result;
            });

            var statisticsArray = (0, _values2.default)(parsedJSON.properties.property);

            var totalTestCount = _AgentUtils.AgentUtils.findMatchingElementInArray(statisticsArray, 'TotalTestCount');
            var passedTestCount = _AgentUtils.AgentUtils.findMatchingElementInArray(statisticsArray, 'PassedTestCount');
            var failedTestCount = _AgentUtils.AgentUtils.findMatchingElementInArray(statisticsArray, 'FailedTestCount');
            var ignoredTestCount = _AgentUtils.AgentUtils.findMatchingElementInArray(statisticsArray, 'IgnoredTestCount');

            resultObject.TotalTestCount = totalTestCount === undefined ? 0 : totalTestCount.$.value;
            resultObject.PassedTestCount = passedTestCount === undefined ? 0 : passedTestCount.$.value;
            resultObject.FailedTestCount = failedTestCount === undefined ? 0 : failedTestCount.$.value;
            resultObject.IgnoredTestCount = ignoredTestCount === undefined ? 0 : ignoredTestCount.$.value;

            return resultObject;
        }
    }]);
    return ExecutorTeamCity;
}(_Executor2.Executor);

_Executor2.Executor.register('TeamCity', ExecutorTeamCity);