"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtensionsManager = void 0;
const tslib_1 = require("tslib");
const markdown_it_1 = tslib_1.__importDefault(require("markdown-it"));
const logger_1 = require("../logger.js");
const ActionsManager_1 = require("./ActionsManager.js");
const ExtensionBuilder_1 = require("./ExtensionBuilder.js");
const ParserTokensRegistry_1 = require("./ParserTokensRegistry.js");
const SchemaSpecRegistry_1 = require("./SchemaSpecRegistry.js");
const SerializerTokensRegistry_1 = require("./SerializerTokensRegistry.js");
class ExtensionsManager {
    static process(extensions, options, logger) {
        return new this({ extensions, options, logger }).build();
    }
    #schemaRegistry;
    #parserRegistry;
    #serializerRegistry;
    #nodeViewCreators = new Map();
    #markViewCreators = new Map();
    #pmTransformers = [];
    #mdForMarkup;
    #mdForText;
    #extensions;
    #builder;
    #spec;
    #deps;
    #plugins = [];
    #actions = {};
    #nodeViews = {};
    #markViews = {};
    #serializerDynamicModifier;
    #parserDynamicModifier;
    constructor({ extensions, options = {}, logger = new logger_1.Logger2() }) {
        this.#schemaRegistry = new SchemaSpecRegistry_1.SchemaSpecRegistry(undefined, options.dynamicModifiers?.schema);
        this.#parserRegistry = new ParserTokensRegistry_1.ParserTokensRegistry({ logger });
        this.#serializerRegistry = new SerializerTokensRegistry_1.SerializerTokensRegistry();
        if (options.dynamicModifiers) {
            this.#parserDynamicModifier = options.dynamicModifiers?.parser;
            this.#serializerDynamicModifier = options.dynamicModifiers?.serializer;
        }
        this.#extensions = extensions;
        const mdPreset = options.mdOpts?.preset ?? 'default';
        this.#mdForMarkup = new markdown_it_1.default(mdPreset, options.mdOpts ?? {});
        this.#mdForText = new markdown_it_1.default(mdPreset, options.mdOpts ?? {});
        if (options.linkifyTlds) {
            this.#mdForMarkup.linkify.tlds(options.linkifyTlds, true);
            this.#mdForText.linkify.tlds(options.linkifyTlds, true);
        }
        if (options.pmTransformers) {
            this.#pmTransformers = options.pmTransformers;
        }
        // TODO: add prefilled context
        this.#builder = new ExtensionBuilder_1.ExtensionBuilder(logger);
    }
    build() {
        this.processExtensions();
        this.createDeps();
        this.createDerived();
        return {
            ...this.#deps,
            actions: this.#deps.actions,
            rawActions: this.#actions,
            plugins: this.#plugins,
            nodeViews: this.#nodeViews,
            markViews: this.#markViews,
        };
    }
    buildDeps() {
        this.processExtensions();
        this.createDeps();
        return this.#deps;
    }
    processExtensions() {
        this.#spec = this.#builder.use(this.#extensions).build();
        this.#mdForMarkup = this.#spec.configureMd(this.#mdForMarkup, 'markup');
        this.#mdForText = this.#spec.configureMd(this.#mdForText, 'text');
        this.#spec.nodes().forEach(this.processNode);
        this.#spec.marks().forEach(this.processMark);
    }
    processNode = (name, { spec, fromMd, toMd, view }) => {
        this.#schemaRegistry.addNode(name, spec);
        this.#parserRegistry.addToken(fromMd.tokenName || name, fromMd.tokenSpec);
        this.#serializerRegistry.addNode(name, toMd);
        if (view) {
            this.#nodeViewCreators.set(name, view);
        }
    };
    processMark = (name, { spec, fromMd, toMd, view }) => {
        this.#schemaRegistry.addMark(name, spec);
        this.#parserRegistry.addToken(fromMd.tokenName || name, fromMd.tokenSpec);
        this.#serializerRegistry.addMark(name, toMd);
        if (view) {
            this.#markViewCreators.set(name, view);
        }
    };
    createParser(schema, mdInstance) {
        return this.#parserRegistry.createParser(schema, mdInstance, this.#pmTransformers, this.#parserDynamicModifier);
    }
    createDeps() {
        const actions = new ActionsManager_1.ActionsManager();
        const schema = this.#schemaRegistry.createSchema();
        const markupParser = this.createParser(schema, this.#mdForMarkup);
        const textParser = this.createParser(schema, this.#mdForText);
        const serializer = this.#serializerRegistry.createSerializer(this.#serializerDynamicModifier);
        this.#deps = {
            schema,
            actions,
            markupParser,
            textParser,
            serializer,
        };
    }
    createDerived() {
        this.#plugins = this.#spec.plugins(this.#deps);
        Object.assign(this.#actions, this.#spec.actions(this.#deps));
        for (const [name, view] of this.#nodeViewCreators) {
            this.#nodeViews[name] = view(this.#deps);
        }
        for (const [name, view] of this.#markViewCreators) {
            this.#markViews[name] = view(this.#deps);
        }
    }
}
exports.ExtensionsManager = ExtensionsManager;
//# sourceMappingURL=ExtensionsManager.js.map
