export const option = CODE_DEMO_OPTIONS;
export const h = (tag, attrs, children) => {
    const node = document.createElement(tag);
    attrs &&
        Object.keys(attrs).forEach((key) => {
            if (!key.indexOf("data")) {
                const k = key.replace("data", "");
                node.dataset[k] = attrs[key];
                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                // @ts-ignore
            }
            else
                node[key] = attrs[key];
        });
    if (children)
        children.forEach((child) => {
            node.appendChild(child);
        });
    return node;
};
const getHtmlTemplate = (html) => `<div id="app">${html}</div>`;
const getReactTemplate = (code) => `${code
    .replace("export default ", "")
    .replace(/App\.__style__(\s*)=(\s*)`([\s\S]*)?`/, "")}ReactDOM.render(React.createElement(App), document.getElementById("app"))`;
const getVueJsTemplate = (js) => `new Vue({ el: '#app', ${js
    .replace(/export\s+default\s*\{(\n*[\s\S]*)\n*\}\s*;?$/u, "$1")
    .replace(/export\s+default\s*Vue\.extend\s*\(\s*\{(\n*[\s\S]*)\n*\}\s*\)\s*;?$/u, "$1")
    .trim()} })`;
const getVueScript = (html, js) => {
    const scripts = js.split(/export\s+default/u);
    const scriptStrOrg = `(function() {${scripts[0]} ; return ${scripts[1]}})()`;
    const scriptStr = window.Babel
        ? window.Babel.transform(scriptStrOrg, { presets: ["es2015"] }).code
        : scriptStrOrg;
    const scriptObj = [eval][0](scriptStr);
    scriptObj.template = html;
    return scriptObj;
};
const getVanillaScript = (js) => window.Babel ? window.Babel.transform(js, { presets: ["es2015"] }).code : js;
export const getVanillaCode = (code, config) => {
    const htmlBlock = /<html>([\s\S]+)<\/html>/u.exec(code);
    const jsBlock = /<script>([\s\S]+)<\/script>/u.exec(code);
    const cssBlock = /<style>([\s\S]+)<\/style>/u.exec(code);
    const html = htmlBlock ? htmlBlock[1].replace(/^\n|\n$/g, "") : "";
    const js = jsBlock ? jsBlock[1].replace(/^\n|\n$/g, "") : "";
    const css = cssBlock ? cssBlock[1].replace(/^\n|\n$/g, "") : "";
    return {
        code: { html, js, css },
        template: { html, js },
        jsLib: config.jsLib || [],
        cssLib: config.cssLib || [],
        script: getVanillaScript(js),
    };
};
export const getVueCode = (code, config) => {
    const htmlBlock = /<template>([\s\S]+)<\/template>/u.exec(code);
    const jsBlock = /<script>([\s\S]+)<\/script>/u.exec(code);
    const cssBlock = /<style>([\s\S]+)<\/style>/u.exec(code);
    const html = htmlBlock ? htmlBlock[1].replace(/^\n|\n$/g, "") : "";
    const js = jsBlock ? jsBlock[1].replace(/^\n|\n$/g, "") : "";
    const css = cssBlock ? cssBlock[1].replace(/^\n|\n$/g, "") : "";
    return {
        code: { html, js, css },
        template: { html: getHtmlTemplate(html), js: getVueJsTemplate(js) },
        jsLib: [option.vue, ...(config.jsLib || [])],
        cssLib: config.cssLib || [],
        script: getVueScript(html, js),
    };
};
export const getReactCode = (code, config) => {
    if (window.Babel) {
        const reactComponent = window.Babel.transform(code, {
            presets: ["es2015", "react"],
        }).code;
        const script = `(function(exports){var module={};module.exports=exports;${reactComponent};return module.exports.__esModule?module.exports.default:module.exports;})({})`;
        // eslint-disable-next-line
        const scriptObj = new Function(`return ${script}`)();
        return {
            code: {
                html: "",
                js: scriptObj,
                css: scriptObj.__style__ || "",
            },
            template: {
                html: getHtmlTemplate(""),
                js: getReactTemplate(code),
            },
            jsLib: [option.react, option.reactDOM, ...(config.jsLib || [])],
            cssLib: config.cssLib || [],
        };
    }
    else
        console.error("Babel not found");
};
export const getCode = (code, config, type) => {
    if (type.includes("react")) {
        const result = /__style__\s*=\s*([`'"])([\s\S]*)\1/u.exec(code);
        return {
            code: { html: "", js: "", css: result ? result[2] : "" },
            template: {
                html: getHtmlTemplate(""),
                js: getReactTemplate(code),
            },
            jsLib: [option.react, option.reactDOM, ...(config.jsLib || [])],
            cssLib: config.cssLib || [],
            preprocessor: {
                html: config.html || "none",
                js: config.js || "none",
                css: config.css || "none",
            },
        };
    }
    if (type.includes("vue")) {
        const htmlBlock = /<template.*?>([\s\S]+)<\/template>/u.exec(code);
        const jsBlock = /<script.*?>([\s\S]+)<\/script>/u.exec(code);
        const cssBlock = /<style.*?>([\s\S]+)<\/style>/u.exec(code);
        const html = htmlBlock ? htmlBlock[1].replace(/^\n|\n$/g, "") : "";
        const js = jsBlock ? jsBlock[1].replace(/^\n|\n$/g, "") : "";
        const css = cssBlock ? cssBlock[1].replace(/^\n|\n$/g, "") : "";
        return {
            code: { html, js, css },
            template: { html: getHtmlTemplate(html), js: getVueJsTemplate(js) },
            jsLib: [option.vue, ...(config.jsLib || [])],
            cssLib: config.cssLib || [],
            preprocessor: {
                html: config.html || "none",
                js: config.js || "none",
                css: config.css || "none",
            },
        };
    }
    const htmlBlock = /<html>([\s\S]+)<\/html>/u.exec(code);
    const jsBlock = /<script>([\s\S]+)<\/script>/u.exec(code);
    const cssBlock = /<style.*?>([\s\S]+)<\/style>/u.exec(code);
    const html = htmlBlock ? htmlBlock[1].replace(/^\n|\n$/g, "") : "";
    const js = jsBlock ? jsBlock[1].replace(/^\n|\n$/g, "") : "";
    const css = cssBlock ? cssBlock[1].replace(/^\n|\n$/g, "") : "";
    return {
        code: { html, js, css },
        template: { html, js },
        jsLib: config.jsLib || [],
        cssLib: config.cssLib || [],
        preprocessor: {
            html: config.html || "none",
            js: config.js || "none",
            css: config.css || "none",
        },
    };
};
const cssStatus = {};
export const injectCSS = (css, id) => {
    if (!cssStatus[id]) {
        const reg = /([\s\S]*?)\{([\s\S]*?)\}/gu;
        let scopeCss = "";
        let result;
        while ((result = reg.exec(css))) {
            const [, selectors, definition] = result;
            scopeCss += `${selectors
                .replace(/\n/g, "")
                .split(",")
                .map((selector) => `#${id} .display-wrapper ${selector}`)
                .join(",")}{${definition}}`;
        }
        const style = h("style", { innerHTML: scopeCss });
        const wrapper = document.querySelector(`#${id}`);
        if (wrapper)
            wrapper.appendChild(style);
        cssStatus[id] = true;
    }
};
