<script lang="ts">
import type { Node, Text, Element, Comment, Root } from 'hast';
import { Text as HText, Comment as HComment } from 'vue';

import ProseP from '~/components/prose/ProseP.vue';
import ProseA from '~/components/prose/ProseA.vue';
import ProseBlockquote from '~/components/prose/ProseBlockquote.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 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, 
    "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, 
    "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: () => ({})
        }
    },
    watch: {
        node: {
            handler: function(val, old) {

            },
            deep: true,
        }
    },
    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;

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

function renderNode(node: Node, tags: Record<string, any>): VNode | undefined
{
    if(node.type === 'text')
    {
        const text = node as Text;
        if(text.value.length > 0 && text.value !== '\n')
            return h(HText, (node as Text).value);
    }
    else if(node.type === 'comment')
    {
        const comment = node as Comment;
        if(comment.value.length > 0 && comment.value !== '\n')
            return h(HComment, (node as Comment).value);
    }
    else if(node.type === 'element')
    {
        const element = node as Element;

        return h(tags[element.tagName], { ...element.properties, class: element.properties.className }, element.children.map(e => renderNode(e, tags)).filter(e => !!e));
    }

    return undefined;
}
</script>