import type { Root, RootContent } from "hast";
import { dom, styling, text, type Class, type Node } from "./dom.util";
import prose, { tag, a, blockquote, h1, h2, h3, h4, h5, hr, li, small, table, td, th, callout, type Prose } from "./proses";
import { heading } from "hast-util-heading";
import { headingRank } from "hast-util-heading-rank";
import { parseId } from "./general.util";
import { loading } from "#shared/proses";

export function renderMarkdown(markdown: Root, proses: Record<string, Prose>): HTMLDivElement
{
    return dom('div', {}, markdown.children.map(e => renderContent(e, proses)));
}

function renderContent(node: RootContent, proses: Record<string, Prose>): Node
{
    if(node.type === 'text' && node.value.length > 0 && node.value !== '\n')
    {
        return text(node.value);
    }
    else if(node.type === 'comment' && node.value.length > 0 && node.value !== '\n')
    {
        return undefined;
    }
    else if(node.type === 'element')
    {
        const children = node.children.map(e => renderContent(e, proses)), properties = { ...node.properties, class: node.properties.className as string | string[] };
        if(node.tagName in proses)
			return prose(node.tagName, proses[node.tagName], children, properties);
		else
			return dom(node.tagName as keyof HTMLElementTagNameMap, properties, children);
    }

    return undefined;
}

export interface MDProperties
{
	class?: Class;
	style?: string | Record<string, string>
}
export default function(content: string, filter?: string, properties?: MDProperties): HTMLElement
{
	const load = loading('normal');

    useMarkdown().parse(content).then(data => {
		if(filter)
			{
				const start = data?.children.findIndex(e => heading(e) && parseId(e.properties.id as string | undefined) === filter) ?? -1;
		
				if(start !== -1)
				{
					let end = start;
					const rank = headingRank(data.children[start])!;
					while(end < data.children.length)
					{
						end++;
						if(heading(data.children[end]) && headingRank(data.children[end])! <= rank)
							break;
					}
					data = { ...data, children: data.children.slice(start, end) };
				}
			}
		
			const el = renderMarkdown(data, { tag, a, blockquote, callout, h1, h2, h3, h4, h5, hr, li, small, table, td, th, });
		
			if(properties) styling(el, properties);

			load.parentElement?.replaceChild(el, load);
	});

	return load;
}