"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
var Suite_1 = require("./Suite");
var UrlSearchParams_1 = require("@dojo/core/UrlSearchParams");
var url_1 = require("url");
var Task_1 = require("@dojo/core/async/Task");
var util_1 = require("./common/util");
var RemoteSuite = (function (_super) {
    __extends(RemoteSuite, _super);
    function RemoteSuite(config) {
        var _this = _super.call(this, config) || this;
        if (_this.timeout == null) {
            _this.timeout = Infinity;
        }
        _this.tests = [];
        return _this;
    }
    RemoteSuite.prototype.run = function () {
        var _this = this;
        var remote = this.remote;
        var sessionId = remote.session.sessionId;
        var server = this.executor.server;
        var listenerHandle;
        var contactTimer;
        var task = new Task_1.default(function (resolve, reject) {
            var handleError = function (error) {
                _this.error = error;
                reject(error);
            };
            listenerHandle = server.subscribe(sessionId, function (name, data) {
                var suite;
                if (contactTimer) {
                    clearTimeout(contactTimer);
                }
                contactTimer = false;
                switch (name) {
                    case 'suiteStart':
                        suite = data;
                        if (!suite.hasParent) {
                            (_a = _this.tests).push.apply(_a, suite.tests);
                            return _this.executor.emit('suiteStart', _this);
                        }
                        else {
                            return _this.executor.emit(name, data);
                        }
                    case 'suiteEnd':
                        suite = data;
                        _this.skipped = suite.skipped;
                        if (!suite.hasParent) {
                            suite.tests.forEach(function (test, index) {
                                _this.tests[index] = test;
                            });
                            if (suite.error) {
                                handleError(suite.error);
                            }
                        }
                        else {
                            return _this.executor.emit(name, data);
                        }
                        break;
                    case 'beforeRun':
                    case 'afterRun':
                    case 'runStart':
                        break;
                    case 'runEnd':
                        var promise = remote.setHeartbeatInterval(0);
                        if (config.excludeInstrumentation !== true) {
                            promise = promise.get('about:blank');
                        }
                        return promise.then(resolve, reject);
                    case 'error':
                        handleError(data);
                        break;
                    default:
                        return _this.executor.emit(name, data);
                }
                var _a;
            });
            var config = _this.executor.config;
            var serverUrlPath = url_1.parse(config.serverUrl).pathname;
            var timeout = config.capabilities['idle-timeout'];
            if (timeout >= 1 && timeout < Infinity) {
                remote.setHeartbeatInterval((timeout - 1) * 1000);
            }
            var queryOptions = {
                basePath: serverUrlPath,
                debug: config.debug,
                sessionId: sessionId,
                socketPort: server.socketPort
            };
            var queryParams = {};
            Object.keys(queryOptions).filter(function (key) {
                return queryOptions[key] != null;
            }).forEach(function (key) {
                var value = queryOptions[key];
                if (typeof value === 'object') {
                    value = JSON.stringify(value);
                }
                queryParams[key] = value;
            });
            var query = new UrlSearchParams_1.default(queryParams);
            var harness = config.serverUrl + "__intern/browser/remote.html";
            var remoteConfig = {
                basePath: serverUrlPath,
                internPath: "" + serverUrlPath + config.internPath,
                name: _this.id,
                sessionId: sessionId
            };
            var excludeKeys = {
                basePath: true,
                capabilities: true,
                contactTimeout: true,
                environmentRetries: true,
                environments: true,
                functionalSuites: true,
                instrumenterOptions: true,
                internPath: true,
                maxConcurrency: true,
                name: true,
                reporters: true,
                serverPort: true,
                sessionId: true,
                socketPort: true,
                tunnel: true,
                tunnelOptions: true,
                webdriver: true
            };
            Object.keys(config).filter(function (key) { return !excludeKeys[key]; }).forEach(function (key) {
                remoteConfig[key] = config[key];
            });
            remote
                .get(harness + "?" + query)
                .execute(function (configString) {
                var options = JSON.parse(configString);
                intern.configure(options);
                intern.run().catch(function (_error) { });
            }, [util_1.toJSON(remoteConfig)])
                .then(function () {
                if (contactTimer !== false) {
                    contactTimer = setTimeout(function () {
                        handleError(new Error('No contact from remote browser'));
                    }, _this.executor.config.contactTimeout);
                }
            })
                .catch(function (error) { return remote.setHeartbeatInterval(0).finally(function () { return handleError(error); }); });
        }, function () { return remote.setHeartbeatInterval(0); }).finally(function () {
            listenerHandle.destroy();
            return _this.executor.emit('suiteEnd', _this);
        });
        return task;
    };
    return RemoteSuite;
}(Suite_1.default));
exports.default = RemoteSuite;
//# sourceMappingURL=RemoteSuite.js.map