import { dirname, join, relative } from "node:path";
import { getSettings } from "../../util/settings.js";
import { MarkdownRenderer, MarkdownSite, rendererLines, } from "../markdown/renderer.js";
function getEmbedPath(embedName) {
    return join(getSettings().output.componentOutDir, "embeds", embedName + ".mdx");
}
function getEmbedSymbol(embedName) {
    return `Embed${embedName}`;
}
export class MdxSite extends MarkdownSite {
    createEmbedPage(embedName) {
        const embedPath = getEmbedPath(embedName);
        if (this.hasPage(embedPath)) {
            return;
        }
        return this.createPage(embedPath);
    }
}
export class MdxRenderer extends MarkdownRenderer {
    #currentPagePath;
    #imports = new Map();
    #includeSidebar = false;
    constructor({ currentPagePath }) {
        super();
        this.#currentPagePath = currentPagePath;
    }
    appendSidebarLink({ title, embedName, }) {
        // If this is a circular import, skip processing sidebar
        if (!this.#insertEmbedImport(embedName)) {
            // TODO: add debug logging
            return;
        }
        this.#includeSidebar = true;
        this.#insertThirdPartyImport("SideBarCta", "@speakeasy-api/docs-md");
        this.#insertThirdPartyImport("SideBar", "@speakeasy-api/docs-md");
        this[rendererLines].push(`<p>
  <SideBarCta cta="${`View ${this.escapeText(title, { escape: "mdx" })}`}" title="${this.escapeText(title, { escape: "mdx" })}">
    <${getEmbedSymbol(embedName)} />
  </SideBarCta>
</p>`);
    }
    // TODO: need to type this properly, but we can't import types from assets
    // since they can't be built as part of this TS project
    appendTryItNow(props) {
        this.#insertThirdPartyImport("TryItNow", "@speakeasy-api/docs-md");
        const escapedProps = Object.fromEntries(Object.entries(props).map(([key, value]) => [
            key,
            typeof value === "string"
                ? this.escapeText(value, { escape: "mdx" })
                : JSON.stringify(value),
        ]));
        this[rendererLines].push(`<TryItNow {...${JSON.stringify(escapedProps)}} externalDependencies={${JSON.stringify(props.externalDependencies)}} defaultValue={\`${props.defaultValue}\`} />`);
    }
    finalize() {
        let imports = "";
        for (const [importPath, symbols] of this.#imports) {
            if (symbols.defaultAlias && symbols.namedImports.size > 0) {
                imports += `import ${symbols.defaultAlias}, { ${Array.from(symbols.namedImports).join(", ")} } from "${importPath}";\n`;
            }
            else if (symbols.defaultAlias) {
                imports += `import ${symbols.defaultAlias} from "${importPath}";\n`;
            }
            else {
                imports += `import { ${Array.from(symbols.namedImports).join(", ")} } from "${importPath}";\n`;
            }
        }
        const parentData = super.finalize();
        const data = (imports ? imports + "\n\n" : "") +
            (this.#includeSidebar ? "<SideBar />\n\n" : "") +
            parentData;
        return data;
    }
    #insertDefaultImport(importPath, symbol) {
        if (!this.#imports.has(importPath)) {
            this.#imports.set(importPath, {
                defaultAlias: undefined,
                namedImports: new Set(),
            });
        }
        // Will never be undefined due to the above. I wish TypeScript could narrow
        // map/set .has() calls
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        this.#imports.get(importPath).defaultAlias = symbol;
    }
    #insertNamedImport(importPath, symbol) {
        if (!this.#imports.has(importPath)) {
            this.#imports.set(importPath, {
                defaultAlias: undefined,
                namedImports: new Set(),
            });
        }
        this.#imports.get(importPath)?.namedImports.add(symbol);
    }
    #insertEmbedImport(embedName) {
        const embedPath = getEmbedPath(embedName);
        // TODO: handle this more gracefully. This happens when we have a direct
        // circular dependency, and the page needs to import itself
        if (this.#currentPagePath === embedPath) {
            return false;
        }
        let importPath = relative(dirname(this.#currentPagePath), embedPath);
        // Check if this is an import to a file in the same directory, which
        // for some reason relative doesn't include the ./ in
        if (!importPath.startsWith("./") && !importPath.startsWith("../")) {
            importPath = `./${importPath}`;
        }
        this.#insertDefaultImport(importPath, getEmbedSymbol(embedName));
        return true;
    }
    #insertThirdPartyImport(symbol, importPath) {
        this.#insertNamedImport(importPath, symbol);
    }
}
//# sourceMappingURL=renderer.js.map