/*****************************************************************************\
|                                               ( )_  _                       |
|    _ _    _ __   _ _    __    ___ ___     _ _ | ,_)(_)  ___   ___     _     |
|   ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| |  | |/',__)/' v `\ /'_`\   |
|   | (_) )| |  ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__,\| (˅) |( (_) )  |
|   | ,__/'(_)  `\__,_)`\__  |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/'  |
|   | |                ( )_) |                                                |
|   (_)                 \___/'                                                |
|                                                                             |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved.             |
| Licensed under the AGPL-3.0.                                                |
|                                                                             |
| According to our dual licensing model,this program can be used either      |
| under the terms of the GNU Affero General Public License,version 3,       |
| or under a proprietary license.                                             |
|                                                                             |
| The texts of the GNU Affero General Public License with an additional       |
| permission and of our proprietary license can be found at and               |
| in the LICENSE file you have received along with this program.              |
|                                                                             |
| This program is distributed in the hope that it will be useful,            |
| but WITHOUT ANY WARRANTY,without even the implied warranty of              |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                |
| GNU Affero General Public License for more details.                         |
|                                                                             |
| "General Bots" is a registered trademark of Pragmatismo.io.                 |
| The licensing of the program under the AGPLv3 does not imply a              |
| trademark license. Therefore any rights,title and interest in              |
| our trademarks remain entirely with us.                                     |
|                                                                             |
\*****************************************************************************/
'use strict';
import { GBLog } from 'botlib';
import { GBServer } from '../../../src/app.js';
import Fs from 'fs';
import SwaggerClient from 'swagger-client';
import { spawn } from 'child_process';
import { CodeServices } from '../../gpt.gblib/services/CodeServices.js';
/**
 * Web Automation services of conversation to be called by BASIC.
 */
export class DebuggerService {
    static systemVariables = [
        'AggregateError',
        'Array',
        'ArrayBuffer',
        'Atomics',
        'BigInt',
        'BigInt64Array',
        'BigUint64Array',
        'Boolean',
        'DataView',
        'Date',
        'Error',
        'EvalError',
        'FinalizationRegistry',
        'Float32Array',
        'Float64Array',
        'Function',
        'Headers',
        'Infinity',
        'Int16Array',
        'Int32Array',
        'Int8Array',
        'Intl',
        'JSON',
        'Map',
        'Math',
        'NaN',
        'Number',
        'Object',
        'Promise',
        'Proxy',
        'RangeError',
        'ReferenceError',
        'Reflect',
        'RegExp',
        'Request',
        'Response',
        'Set',
        'SharedArrayBuffer',
        'String',
        'Symbol',
        'SyntaxError',
        'TypeError',
        'URIError',
        'Uint16Array',
        'Uint32Array',
        'Uint8Array',
        'Uint8ClampedArray',
        'VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL',
        'WeakMap',
        'WeakRef',
        'WeakSet',
        'WebAssembly',
        '__defineGetter__',
        '__defineSetter__',
        '__lookupGetter__',
        '__lookupSetter__',
        '__proto__',
        'clearImmediate',
        'clearInterval',
        'clearTimeout',
        'console',
        'constructor',
        'decodeURI',
        'decodeURIComponent',
        'dss',
        'encodeURI',
        'encodeURIComponent',
        'escape',
        'eval',
        'fetch',
        'global',
        'globalThis',
        'hasOwnProperty',
        'isFinite',
        'isNaN',
        'isPrototypeOf',
        'parseFloat',
        'parseInt',
        'process',
        'propertyIsEnumerable',
        'setImmediate',
        'setInterval',
        'setTimeout',
        'toLocaleString',
        'toString',
        'undefined',
        'unescape',
        'valueOf'
    ];
    async setBreakpoint({ botId, line }) {
        GBLog.info(`BASIC: Enabled breakpoint for ${botId} on ${line}.`);
        GBServer.globals.debuggers[botId].breaks.push(Number.parseInt(line));
    }
    async refactor({ botId, code, change }) {
        const service = new CodeServices();
        return await service.refactor(code, change);
    }
    async resume({ botId }) {
        if (GBServer.globals.debuggers[botId].state === 2) {
            const client = GBServer.globals.debuggers[botId].client;
            await client.Debugger.resume();
            GBServer.globals.debuggers[botId].state = 1;
            GBServer.globals.debuggers[botId].stateInfo = 'Running (Debug)';
            return { status: 'OK' };
        }
        else {
            const error = 'Invalid call to resume and state not being debug(2).';
            return { error: error };
        }
    }
    async stop({ botId }) {
        GBServer.globals.debuggers[botId].state = 0;
        GBServer.globals.debuggers[botId].stateInfo = 'Stopped';
        const kill = ref => {
            spawn('sh', ['-c', `pkill -9 -f ${ref}`]);
        };
        kill(GBServer.globals.debuggers[botId].childProcess);
        return { status: 'OK' };
    }
    async step({ botId }) {
        if (GBServer.globals.debuggers[botId].state === 2) {
            GBServer.globals.debuggers[botId].stateInfo = 'Break';
            const client = GBServer.globals.debuggers[botId].client;
            await client.Debugger.stepOver();
            return { status: 'OK' };
        }
        else {
            const error = 'Invalid call to stepOver and state not being debug(2).';
            return { error: error };
        }
    }
    async getContext({ botId }) {
        const conversationsMap = GBServer.globals.debuggers[botId].conversationsMap;
        const watermarkMap = GBServer.globals.debuggers[botId].watermarkMap;
        const conversationId = conversationsMap[botId];
        let messages = [];
        const client = GBServer.globals.debuggers[botId].client;
        if (client) {
            const response = await client.apis.Conversations.Conversations_GetActivities({
                conversationId: conversationId,
                watermark: watermarkMap[botId]
            });
            watermarkMap[botId] = response.obj.watermark;
            let activities = response.obj.activites;
            if (activities && activities.length) {
                activities = activities.filter(m => m.from.id === botId && m.type === 'message');
                if (activities.length) {
                    activities.forEach(activity => {
                        messages.push({ text: activity.text });
                        GBLog.info(`Debugger sending text to API: ${activity.text}`);
                    });
                }
            }
        }
        let messagesText = messages.join('\n');
        return {
            status: 'OK',
            state: GBServer.globals.debuggers[botId].state,
            messages: messagesText,
            scope: GBServer.globals.debuggers[botId].scope,
            scopeInfo: GBServer.globals.debuggers[botId].stateInfo
        };
    }
    async start({ botId, botApiKey, scriptName }) {
        const conversationsMap = GBServer.globals.debuggers[botId].conversationsMap;
        let error;
        if (!GBServer.globals.debuggers[botId]) {
            GBServer.globals.debuggers[botId] = {};
        }
        if (!scriptName) {
            scriptName = 'start';
        }
        if (GBServer.globals.debuggers[botId].state === 1) {
            error = `Cannot DEBUG an already running process. ${botId}`;
            return { error: error };
        }
        else if (GBServer.globals.debuggers[botId].state === 2) {
            GBLog.info(`BASIC: Releasing execution ${botId} in DEBUG mode.`);
            await this.resume({ botId });
            return { status: 'OK' };
        }
        else {
            GBLog.info(`BASIC: Running ${botId} in DEBUG mode.`);
            GBServer.globals.debuggers[botId].state = 1;
            GBServer.globals.debuggers[botId].stateInfo = 'Running (Debug)';
            let min = GBServer.globals.minInstances.filter(p => p.instance.botId === botId)[0];
            const client = await new SwaggerClient({
                spec: JSON.parse(Fs.readFileSync('directline-3.0.json', 'utf8')),
                requestInterceptor: req => {
                    req.headers['Authorization'] = `Bearer ${min.instance.webchatKey}`;
                }
            });
            GBServer.globals.debuggers[botId].client = client;
            const response = await client.apis.Conversations.Conversations_StartConversation();
            const conversationId = response.obj.conversationId;
            GBServer.globals.debuggers[botId].conversationId = conversationId;
            client.apis.Conversations.Conversations_PostActivity({
                conversationId: conversationId,
                activity: {
                    textFormat: 'plain',
                    text: `/calldbg ${scriptName}`,
                    type: 'message',
                    from: {
                        id: 'word',
                        name: 'word'
                    }
                }
            });
            return { status: 'OK' };
        }
    }
    async sendMessage({ botId, botApiKey, text }) {
        const conversationsMap = GBServer.globals.debuggers[botId].conversationsMap;
        let error;
        if (!GBServer.globals.debuggers[botId]) {
            GBServer.globals.debuggers[botId] = {};
        }
        if (GBServer.globals.debuggers[botId].state != 1) {
            error = `Cannot sendMessage to an stopped process. ${botId}`;
            return { error: error };
        }
        let min = GBServer.globals.minInstances.filter(p => p.instance.botId === botId)[0];
        const client = GBServer.globals.debuggers[botId].client;
        const conversationId = GBServer.globals.debuggers[botId].conversationId;
        client.apis.Conversations.Conversations_PostActivity({
            conversationId: conversationId,
            activity: {
                textFormat: 'plain',
                text: text,
                type: 'message',
                from: {
                    id: 'word',
                    name: 'word'
                }
            }
        });
        return { status: 'OK' };
    }
}
//# sourceMappingURL=DebuggerService.js.map