"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.ActualCode = void 0;var _reporter = require("./reporter");
var _source = require("../source");

var _nodeJs = _interopRequireDefault(require("../plugins/node-js"));
var _shell = _interopRequireDefault(require("../plugins/shell"));
var _html = _interopRequireDefault(require("../plugins/html"));

var _sandbox = require("./sandbox");function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _defineProperty(obj, key, value) {if (key in obj) {Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });} else {obj[key] = value;}return obj;}








































class ActualCode {









  constructor(id, storage) {_defineProperty(this, "_reporter", new _reporter.Reporter());_defineProperty(this, "_init", void 0);_defineProperty(this, "_runningState", null);_defineProperty(this, "_sandbox", void 0);_defineProperty(this, "id", void 0);_defineProperty(this, "_storage", void 0);_defineProperty(this, "_plugins", [_nodeJs.default, _shell.default, _html.default]);_defineProperty(this, "_resultProcessors", []);
    this.id = id;
    this._storage = storage;
    const init = async () => {
      this._sandbox = new _sandbox.ActualCodeSandbox(this, this._reporter);
      for (const plugin of this._plugins) {
        await this._addPlugin(plugin);
      }
    };
    this._init = init();
  }

  async _addPlugin(plugin) {
    const { name, sandbox, resultProcessor } = plugin();
    this._reporter.event('register plugin', { name });
    if (sandbox) {
      await this._sandbox.addPlugin(sandbox);
    }
    if (resultProcessor) {
      this._resultProcessors.push(resultProcessor);
    }
  }

  async registerPlugin(plugin) {
    if (typeof plugin === 'string') {
      await this._addPlugin(eval(plugin));
    } else {
      await this._addPlugin(plugin);
    }
  }

  async getAppState() {
    return this._storage.readById(this.id);
  }

  async run(code, opts) {
    await this._init;
    const { settings, root } = await (0, _source.parse)(code);
    const codeBlocks = await (0, _source.getCodeBlocks)(root);

    const resultProcessors = [];
    for (const plugin of this._resultProcessors) {
      resultProcessors.push((await plugin(root, codeBlocks)));
    }

    const results = {};

    this._reporter.setCallback(async report => {
      await this._init;

      for (const p of resultProcessors) {
        if (p.transform) {
          report = await p.transform(report);
          if (!report) {
            return;
          }
        }
      }

      if (!(report.hash in results)) {
        results[report.hash] = [];
      }
      results[report.hash].push(report);
    });

    const outputProcessor = resultProcessors.find(p => 'output' in p);

    const runner = async () => {
      this._reporter.debug('run markdown script');

      for (const codeBlock of codeBlocks) {
        await this._sandbox.run(codeBlock, opts);
      }

      if (opts.runMode) {
        await this.save(code, results);
      }
      if (outputProcessor) {
        return outputProcessor.output(results);
      } else {
        return null;
      }
    };
    this._runningState = runner();

    if (outputProcessor) {
      return outputProcessor.output(null);
    } else {
      return null;
    }
  }

  async save(code, results) {
    await this._init;

    if (this._storage) {
      await this._storage.updateAppState(this.id, code, results);
    }
  }

  async waitFinished() {
    const result = await this._runningState;
    this._runningState = null;
    return result;
  }}exports.ActualCode = ActualCode;