/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. All rights reserved.
 *--------------------------------------------------------*/
"use strict";
const os = require("os");
const vscode_debugadapter_1 = require("vscode-debugadapter");
function isMessage(e) {
    return !!e.format;
}
function isChromeError(e) {
    return !!e.data;
}
class ChromeDebugSession extends vscode_debugadapter_1.LoggingDebugSession {
    /**
     * This needs a bit of explanation -
     * The Session is reinstantiated for each session, but consumers need to configure their instance of
     * ChromeDebugSession. Consumers should call getSession with their config options, then call
     * DebugSession.run with the result. Alternatively they could subclass ChromeDebugSession and pass
     * their options to the super constructor, but I think this is easier to follow.
     */
    static getSession(opts) {
        // class expression!
        return class extends ChromeDebugSession {
            constructor(debuggerLinesAndColumnsStartAt1, isServer) {
                super(debuggerLinesAndColumnsStartAt1, isServer, opts);
            }
        };
    }
    constructor(obsolete_debuggerLinesAndColumnsStartAt1, obsolete_isServer, opts) {
        super(opts.logFilePath, obsolete_debuggerLinesAndColumnsStartAt1, obsolete_isServer);
        logVersionInfo();
        this._extensionName = opts.extensionName;
        this._debugAdapter = new opts.adapter(opts, this);
        const safeGetErrDetails = err => {
            let errMsg;
            try {
                errMsg = err.stack ? err.stack : JSON.stringify(err);
            }
            catch (e) {
                errMsg = 'Error while handling previous error: ' + e.stack;
            }
            return errMsg;
        };
        process.on('uncaughtException', (err) => {
            vscode_debugadapter_1.logger.error(`******** Unhandled error in debug adapter: ${safeGetErrDetails(err)}`);
            throw err;
        });
        process.addListener('unhandledRejection', (err) => {
            // Node tests are watching for the ********, so fix the tests if it's changed
            vscode_debugadapter_1.logger.error(`******** Unhandled error in debug adapter - Unhandled promise rejection: ${safeGetErrDetails(err)}`);
        });
    }
    /**
     * Takes a response and a promise to the response body. If the promise is successful, assigns the response body and sends the response.
     * If the promise fails, sets the appropriate response parameters and sends the response.
     */
    sendResponseAsync(request, response, responseP) {
        responseP.then((body) => {
            response.body = body;
            this.sendResponse(response);
        }, e => this.failedRequest(request.command, response, e));
    }
    /**
     * Overload dispatchRequest to the debug adapters' Promise-based methods instead of DebugSession's callback-based methods
     */
    dispatchRequest(request) {
        const response = new vscode_debugadapter_1.Response(request);
        try {
            vscode_debugadapter_1.logger.verbose(`From client: ${request.command}(${JSON.stringify(request.arguments)})`);
            if (!(request.command in this._debugAdapter)) {
                this.sendUnknownCommandResponse(response, request.command);
                return;
            }
            const responseP = Promise.resolve(this._debugAdapter[request.command](request.arguments, request.seq));
            this.sendResponseAsync(request, response, responseP);
        }
        catch (e) {
            this.failedRequest(request.command, response, e);
        }
    }
    failedRequest(requestType, response, error) {
        if (isMessage(error)) {
            this.sendErrorResponse(response, error);
            return;
        }
        if (requestType === 'evaluate') {
            // Errors from evaluate show up in the console or watches pane. Doesn't seem right
            // as it's not really a failed request. So it doesn't need the [extensionName] tag and worth special casing.
            response.message = error ? error.message : 'Unknown error';
            response.success = false;
            this.sendResponse(response);
            return;
        }
        const errMsg = isChromeError(error) ?
            error.message + ': ' + error.data :
            (error.stack || error.message);
        vscode_debugadapter_1.logger.error(`Error processing "${requestType}": ${errMsg}`);
        // These errors show up in the message bar at the top (or nowhere), sometimes not obvious that they
        // come from the adapter, so add extensionName
        this.sendErrorResponse(response, 1104, '[{_extensionName}] Error processing "{_requestType}": {_stack}', { _extensionName: this._extensionName, _requestType: requestType, _stack: errMsg }, vscode_debugadapter_1.ErrorDestination.Telemetry);
    }
    sendUnknownCommandResponse(response, command) {
        this.sendErrorResponse(response, 1014, `[${this._extensionName}] Unrecognized request: ${command}`, null, vscode_debugadapter_1.ErrorDestination.Telemetry);
    }
}
exports.ChromeDebugSession = ChromeDebugSession;
function logVersionInfo() {
    vscode_debugadapter_1.logger.log(`OS: ${os.platform()} ${os.arch()}`);
    vscode_debugadapter_1.logger.log(`Adapter node: ${process.version} ${process.arch}`);
    vscode_debugadapter_1.logger.log('vscode-chrome-debug-core: ' + require('../../../package.json').version);
}

//# sourceMappingURL=chromeDebugSession.js.map
