"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const LoadableComponent = __importStar(require("@loadable/component"));
const server_1 = require("@loadable/server");
const React = __importStar(require("react"));
const ReactDOM = __importStar(require("react-dom"));
const server_2 = require("react-dom/server");
const micro_core_1 = require("@vtex/micro-core");
const container_1 = require("../../components/container");
const data_1 = require("../../components/data");
const runtime_1 = require("../../components/runtime");
global.React = React;
global.ReactDOM = ReactDOM;
global.LoadableComponent = LoadableComponent;
class Render extends micro_core_1.RenderFrameworkHook {
    constructor(options) {
        var _a;
        super(options);
        this.webExtractor = null;
        this.nodeExtractor = null;
        this.render = (element) => element;
        this.renderToString = (element) => {
            let ssr = '';
            if (element) {
                const wrapped = this.webExtractor
                    ? this.webExtractor.collectChunks(element)
                    : element;
                ssr = server_2.renderToString(wrapped);
            }
            return container_1.withAppContainerTags(ssr);
        };
        this.requireEntrypoint = () => {
            const { project, page: { name, data }, } = this.options;
            this.nodeExtractor.requireEntrypoint();
            const { default: Page } = global[`${project.root.toString()}/pages`];
            // TODO: Figure out a way to the error come from the router
            return React.createElement(Page, { name, data, error: null });
        };
        this.getScriptTags = () => {
            var _a, _b;
            const { publicPaths, page } = this.options;
            const tags = [];
            tags.push(runtime_1.withRuntimeTags({ publicPaths, page }));
            tags.push((_b = (_a = this.webExtractor) === null || _a === void 0 ? void 0 : _a.getScriptTags()) !== null && _b !== void 0 ? _b : '');
            return tags.join('\n');
        };
        this.getStyleTags = () => {
            var _a, _b;
            // if (typeof (this.webExtractor as any).getMainAssets === 'function') {
            //   const assets = (this.webExtractor as any).getMainAssets('style')
            //   return assets
            //     .map(({ path, chunk }: { path: string; chunk: string }) => {
            //       const content = readFileSync(path)
            //       return `<style data-chunk="${chunk}" rel="stylesheet">${content}</style>`
            //     })
            //     .join('\n')
            // }
            // return ''
            return (_b = (_a = this.webExtractor) === null || _a === void 0 ? void 0 : _a.getStyleTags()) !== null && _b !== void 0 ? _b : '';
        };
        this.getLinkTags = () => {
            var _a;
            const { page: { name, data }, publicPaths: { data: rootPath }, path, } = this.options;
            const tagsNoCSS = (_a = this.webExtractor) === null || _a === void 0 ? void 0 : _a.getLinkTags();
            // .split('\n')
            // .filter((x) => !x.includes('as="style"'))
            // .join('\n')
            const dataTags = data_1.withPageDataTags({ name, data, rootPath, path });
            return [tagsNoCSS, dataTags].join('\n');
            // return [
            //   dataTags,
            //   this.extractor.getLinkTags()
            // ].join('\n')
        };
        this.getMetaTags = () => [
            '<meta name="viewport" content="width=device-width, initial-scale=1">',
            '<meta name="generator" content="micro@1.x">',
            "<meta charset='utf-8'>",
        ].join('\n');
        if (!((_a = this.options.stats) === null || _a === void 0 ? void 0 : _a.children)) {
            return;
        }
        let webStats = null;
        let nodeStats = null;
        for (const child of options.stats.children) {
            switch (child.name) {
                case 'web-legacy':
                case 'web':
                    webStats = child;
                    break;
                case 'pages':
                    nodeStats = child;
                    break;
                case 'components':
                case 'route':
                case 'render':
                    break;
                default:
                    throw new Error('💣 Stats name not expected');
            }
        }
        if (webStats) {
            this.webExtractor = new server_1.ChunkExtractor({
                entrypoints: ['index'],
                publicPath: options.publicPaths.assets,
                stats: webStats,
            });
        }
        if (nodeStats) {
            this.nodeExtractor = new server_1.ChunkExtractor({
                entrypoints: ['index'],
                stats: nodeStats,
            });
        }
    }
}
exports.default = Render;
