<script lang="ts">
import type { RootContent, Root } from 'hast';
import { Text, Comment } from 'vue';

import ProseP from '~/components/prose/ProseP.vue';
import ProseA from '~/components/prose/ProseA.vue';
import ProseBlockquote from '~/components/prose/ProseBlockquote.vue';
import ProseCallout from './prose/ProseCallout.vue';
import ProseCode from '~/components/prose/ProseCode.vue';
import ProsePre from '~/components/prose/ProsePre.vue';
import ProseEm from '~/components/prose/ProseEm.vue';
import ProseH1 from '~/components/prose/ProseH1.vue';
import ProseH2 from '~/components/prose/ProseH2.vue';
import ProseH3 from '~/components/prose/ProseH3.vue';
import ProseH4 from '~/components/prose/ProseH4.vue';
import ProseH5 from '~/components/prose/ProseH5.vue';
import ProseH6 from '~/components/prose/ProseH6.vue';
import ProseHr from '~/components/prose/ProseHr.vue';
import ProseImg from '~/components/prose/ProseImg.vue';
import ProseUl from '~/components/prose/ProseUl.vue';
import ProseOl from '~/components/prose/ProseOl.vue';
import ProseLi from '~/components/prose/ProseLi.vue';
import ProseStrong from '~/components/prose/ProseStrong.vue';
import ProseTable from '~/components/prose/ProseTable.vue';
import ProseTag from '~/components/prose/ProseTag.vue';
import ProseThead from '~/components/prose/ProseThead.vue';
import ProseTbody from '~/components/prose/ProseTbody.vue';
import ProseTd from '~/components/prose/ProseTd.vue';
import ProseTh from '~/components/prose/ProseTh.vue';
import ProseTr from '~/components/prose/ProseTr.vue';
import ProseScript from '~/components/prose/ProseScript.vue';

const proseList = {
    "p": ProseP,
    "a": ProseA,
    "blockquote": ProseBlockquote,
    "callout": ProseCallout,
    "code": ProseCode,
    "pre": ProsePre,
    "em": ProseEm,
    "h1": ProseH1,
    "h2": ProseH2,
    "h3": ProseH3,
    "h4": ProseH4,
    "h5": ProseH5,
    "h6": ProseH6,
    "hr": ProseHr,
    "img": ProseImg,
    "ul": ProseUl,
    "ol": ProseOl,
    "li": ProseLi,
    "strong": ProseStrong,
    "table": ProseTable,
    "tag": ProseTag,
    "thead": ProseThead,
    "tbody": ProseTbody,
    "td": ProseTd,
    "th": ProseTh,
    "tr": ProseTr,
    "script": ProseScript
};

export default defineComponent({
    name: 'MarkdownRenderer',
    props: {
        node: {
            type: Object,
            required: true
        },
        proses: {
            type: Object,
            default: () => ({})
        }
    },
    async setup(props) {
        if(props.proses)
        {
            for(const prose of Object.keys(props.proses))
            {
                if(typeof props.proses[prose] === 'string')
                    props.proses[prose] = await resolveComponent(props.proses[prose]);
            }
        }
        return { tags: Object.assign({}, proseList, props.proses) };
    },
    render(ctx: any) {
        const { node, tags } = ctx;

        if(!node)
            return null;

        return h('div', null, {default: () => (node as Root).children.map(e => renderNode(e, tags)).filter(e => !!e)});
    }
});

function renderNode(node: RootContent, tags: Record<string, any>): VNode | undefined
{
    if(node.type === 'text' && node.value.length > 0 && node.value !== '\n')
    {
        return h(Text, node.value);
    }
    else if(node.type === 'comment' && node.value.length > 0 && node.value !== '\n')
    {
        return h(Comment, node.value);
    }
    else if(node.type === 'element')
    {
        return h(tags[node.tagName] ?? node.tagName, { ...node.properties, class: node.properties.className }, { default: () => node.children.map(e => renderNode(e, tags)).filter(e => !!e) });
    }

    return undefined;
}
</script>