import { dom, icon, type NodeChildren, type Node, type NodeProperties, type Class, mergeClasses } from "#shared/dom.util";
import { parseURL } from 'ufo';
import render from "#shared/markdown.util";
import { popper } from "#shared/floating.util";
import { Canvas } from "#shared/canvas.util";
import { Content, iconByType, type LocalContent } from "#shared/content.util";
import type { RouteLocationAsRelativeTyped, RouteMapGeneric } from "vue-router";
import { unifySlug } from "#shared/general.util";

export type CustomProse = (properties: any, children: NodeChildren) => Node;
export type Prose = { class: string } | { custom: CustomProse };
export const tag: Prose = {
    custom(properties, children) {
        const tag = properties.tag as string;
        const el = dom('span', { class: "before:content-['#'] cursor-default bg-accent-blue bg-opacity-10 hover:bg-opacity-20 text-accent-blue text-sm px-1 ms-1 pb-0.5 rounded-full rounded-se-none border border-accent-blue border-opacity-30" }, children);
        const overview = Content.getFromPath('tags');

        let rendered = false;

        if(!!overview)
        {
            popper(el, {
                arrow: true,
                delay: 150,
                offset: 10,
                placement: 'bottom-start',
                class: 'data-[side=bottom]:animate-slideUpAndFade data-[side=right]:animate-slideLeftAndFade data-[side=left]:animate-slideRightAndFade data-[side=top]:animate-slideDownAndFade w-[300px] bg-light-10 dark:bg-dark-10 border border-light-35 dark:border-dark-35 data-[state=open]:transition-transform text-light-100 dark:text-dark-100 max-w-[600px] max-h-[600px] w-full z-[45]',
                content: [loading("large")],
                onShow(content: HTMLDivElement) {
                    if(!rendered)
                    {
                        Content.getContent(overview.id).then((_content) => {
                            content.replaceChild(render((_content as LocalContent<'markdown'>).content ?? '', tag, { class: 'max-w-[600px] max-h-[600px] w-full overflow-auto py-4 px-6' }), content.children[0]);
                        });
                        rendered = true;
                    }
                },
            });
        }

        return el;
    }
}
export const a: Prose = {
    custom(properties, children) {
        const href = properties.href as string;
        const { hash, pathname } = parseURL(href);
        const router = useRouter();

        const overview = Content.getFromPath(pathname === '' && hash.length > 0 ?  unifySlug(router.currentRoute.value.params.path) : pathname);

        const link = overview ? { name: 'explore-path', params: { path: overview.path }, hash: hash } : href, nav = router.resolve(link);
        
        let rendered = false;

        const el = dom('a', { class: 'text-accent-blue inline-flex items-center', attributes: { href: nav.href }, listeners: {
                'click': (e) => {
                e.preventDefault();
                router.push(link);
            }
        }}, [
            dom('span', {}, [
                ...(children ?? []),
                overview && overview.type !== 'markdown' ? icon(iconByType[overview.type], { class: 'w-4 h-4 inline-block', inline: true }) : undefined
            ])
        ]);

        if(!!overview)
        {
            popper(el, {
                arrow: true,
                delay: 150,
                offset: 12,
                placement: 'bottom-start',
                class: 'data-[side=bottom]:animate-slideUpAndFade data-[side=right]:animate-slideLeftAndFade data-[side=left]:animate-slideRightAndFade data-[side=top]:animate-slideDownAndFade w-[300px] bg-light-10 dark:bg-dark-10 border border-light-35 dark:border-dark-35 data-[state=open]:transition-transform text-light-100 dark:text-dark-100 min-w-[200px] min-h-[150px] max-w-[600px] max-h-[600px] w-full z-[45]',
                content: [loading("large")],
                onShow(content: HTMLDivElement) {
                    if(!rendered)
                    {
                        console.log('')
                        Content.getContent(overview.id).then((_content) => {
                            if(_content?.type === 'markdown')
                            {
                                content.replaceChild(render((_content as LocalContent<'markdown'>).content ?? '', hash.length > 0 ? hash.substring(1) : undefined, { class: 'min-w-[200px] min-h-[150px] max-w-[600px] max-h-[600px] w-full overflow-auto py-4 px-6' }), content.children[0]);
                            }
                            if(_content?.type === 'canvas')
                            {
                                const canvas = new Canvas((_content as LocalContent<'canvas'>).content);
                                content.replaceChild(dom('div', { class: 'w-[600px] h-[600px] relative' }, [canvas.container]), content.children[0]);
                                canvas.mount();
                            }
                        });
                        rendered = true;
                    }
                },
            });
        }

        return el;
    }
}
export const fakeA: Prose = {
    custom(properties, children) {
        const href = properties.href as string;
        const { hash, pathname } = parseURL(href);
        const router = useRouter();

        const overview = Content.getFromPath(pathname === '' && hash.length > 0 ?  unifySlug(router.currentRoute.value.params.path) : pathname);
        
        const el = dom('span', { class: 'cursor-pointer text-accent-blue inline-flex items-center' }, [
            dom('span', {}, [
                ...(children ?? []),
                overview && overview.type !== 'markdown' ? icon(iconByType[overview.type], { class: 'w-4 h-4 inline-block', inline: true }) : undefined
            ])
        ]);

        if(!!overview)
        {
            const magicKeys = useMagicKeys();
            popper(el, {
                arrow: true,
                delay: 150,
                offset: 12,
                placement: 'bottom-start',
                class: 'data-[side=bottom]:animate-slideUpAndFade data-[side=right]:animate-slideLeftAndFade data-[side=left]:animate-slideRightAndFade data-[side=top]:animate-slideDownAndFade w-[300px] bg-light-10 dark:bg-dark-10 border border-light-35 dark:border-dark-35 data-[state=open]:transition-transform text-light-100 dark:text-dark-100 min-w-[200px] min-h-[150px] max-w-[600px] max-h-[600px] w-full z-[45]',
                content: [loading("large")],
                onShow(content: HTMLDivElement) {
                    if(!magicKeys.current.has('control') || magicKeys.current.has('meta'))
                        return false;

                    content.replaceChild(loading("large"), content.children[0]);
                    Content.getContent(overview.id).then((_content) => {
                        if(_content?.type === 'markdown')
                        {
                            content.replaceChild(render((_content as LocalContent<'markdown'>).content ?? '', hash.length > 0 ? hash.substring(1) : undefined, { class: 'min-w-[200px] min-h-[150px] max-w-[600px] max-h-[600px] w-full overflow-auto py-4 px-6' }), content.children[0]);
                        }
                        if(_content?.type === 'canvas')
                        {
                            const canvas = new Canvas((_content as LocalContent<'canvas'>).content);
                            content.replaceChild(dom('div', { class: 'w-[600px] h-[600px] relative' }, [canvas.container]), content.children[0]);
                            canvas.mount();
                        }
                    });
                },
            });
        }

        return el;
    }
}
export const callout: Prose = {
    custom(properties, children) {
        const calloutIconByType: Record<string, string> = {
            note: 'radix-icons:pencil-1',
            abstract: 'radix-icons:file-text',
            info: 'radix-icons:info-circled',
            todo: 'radix-icons:check-circled',
            tip: 'radix-icons:star',
            success: 'radix-icons:check',
            question: 'radix-icons:question-mark-circled',
            warning: 'radix-icons:exclamation-triangle',
            failure: 'radix-icons:cross-circled',
            danger: 'radix-icons:circle-backslash',
            bug: 'solar:bug-linear',
            example: 'radix-icons:list-bullet',
            quote: 'radix-icons:quote',
        };
        const defaultCalloutIcon = 'radix-icons:info-circled';

        const {	type, title, fold }: {
            type: string;
            title?: string;
            fold?: boolean;
        } = properties;

        let open = fold;
        const trigger = dom('div', { class: [{'cursor-pointer': fold !== undefined}, 'flex flex-row items-center justify-start ps-2'] }, [icon(calloutIconByType[type] ?? defaultCalloutIcon, { inline: true, width: 24, height: 24, class: 'w-6 h-6 stroke-2 float-start me-2 flex-shrink-0' }), !!title ? dom('span', { class: 'block font-bold text-start', text: title }) : undefined, fold !== undefined ? icon('radix-icons:caret-right', { height: 24, width: 24, class: 'transition-transform group-data-[state=open]:rotate-90 w-6 h-6 mx-6' }) : undefined]);
        const container = dom('div', { class: 'callout group overflow-hidden my-4 p-3 ps-4 bg-blend-lighten !bg-opacity-25 border-l-4 inline-block pe-8 bg-light-blue dark:bg-dark-blue', attributes: { 'data-state': fold !== false ? 'closed' : 'open', 'data-type': type } }, [
            trigger,
            dom('div', { class: 'overflow-hidden group-data-[state=closed]:animate-[collapseClose_0.2s_ease-in-out] group-data-[state=open]:animate-[collapseOpen_0.2s_ease-in-out] group-data-[state=closed]:h-0' }, [
                dom('div', { class: 'px-2' }, children),
            ])
        ]);

        trigger.addEventListener('click', e => {
            container.setAttribute('data-state', open ? 'open' : 'closed');
            open = !open;
        })

        return container;
    },
}
export const blockquote: Prose = {
    class: 'empty:before:hidden ps-4 my-4 relative before:absolute before:-top-1 before:-bottom-1 before:left-0 before:w-1 before:bg-light-30 dark:before:bg-dark-30',
}
export const h1: Prose = {
    class: 'text-5xl font-thin mt-3 mb-8 first:pt-0 pt-2',
}
export const h2: Prose = {
    class: 'text-4xl font-semibold mt-3 mb-6 ms-1 first:pt-0 pt-2',
}
export const h3: Prose = {
    class: 'text-2xl font-bold  mt-2 mb-4',
}
export const h4: Prose = {
    class: 'text-xl font-semibold my-2',
}
export const h5: Prose = {
    class: 'text-lg font-semibold my-1',
}
export const hr: Prose = {
    class: 'border-b border-light-35 dark:border-dark-35 m-4',
}
export const li: Prose = {
    class: 'before:absolute before:top-2 before:left-0 before:inline-block before:w-2 before:h-2 before:rounded before:bg-light-40 dark:before:bg-dark-40 relative ps-4',
}
export const small: Prose = {
    class: 'text-light-60 dark:text-dark-60 text-sm italic',
}
export const table: Prose = {
    class: 'mx-4 my-8 border-collapse border border-light-35 dark:border-dark-35',
}
export const td: Prose = {
    class: 'border border-light-35 dark:border-dark-35 py-1 px-2',
}
export const th: Prose = {
    class: 'border border-light-35 dark:border-dark-35 px-4 first:pt-0',
}

export default function(tag: string, prose: Prose, children?: NodeChildren, properties?: any): Node
{
    if('class' in prose)
    {
        return dom(tag as keyof HTMLElementTagNameMap, { class: [properties?.class, prose.class] }, children ?? []);
    }
    else
    {
        return prose.custom(properties, children ?? []);
    }
}

export function link(properties?: NodeProperties & { active?: Class }, link?: RouteLocationAsRelativeTyped<RouteMapGeneric, string>, children?: NodeChildren)
{
    const router = useRouter();
    const nav = link ? router.resolve(link) : undefined;
    return dom('a', { ...properties, class: [properties?.class, properties?.active && router.currentRoute.value.fullPath === nav?.fullPath ? properties.active : undefined], attributes: { href: nav?.href, 'data-active': properties?.active ? mergeClasses(properties?.active) : undefined }, listeners: link ? {
        click: function(e)
        {
            e.preventDefault();
            router.push(link);
        }
    } : undefined }, children);
}
export function loading(size: 'small' | 'normal' | 'large' = 'normal'): HTMLElement
{
    return dom('span', { class: ["after:block after:relative after:rounded-full after:border-transparent after:border-t-accent-purple after:animate-spin", {'w-6 h-6 border-4 border-transparent after:-top-[4px] after:-left-[4px] after:w-6 after:h-6 after:border-4': size === 'normal', 'w-4 h-4 after:-top-[2px] after:-left-[2px] after:w-4 after:h-4 after:border-2': size === 'small', 'w-12 h-12 after:-top-[6px] after:-left-[6px] after:w-12 after:h-12 after:border-[6px]': size === 'large'}] })
}
export function button(content: Node, onClick?: () => void, cls?: Class)
{
    return dom('button', { class: [`text-light-100 dark:text-dark-100 font-semibold hover:bg-light-30 dark:hover:bg-dark-30 inline-flex items-center justify-center bg-light-25 dark:bg-dark-25 leading-none outline-none
    border border-light-25 dark:border-dark-25 hover:border-light-30 dark:hover:border-dark-30 active:border-light-40 dark:active:border-dark-40 focus:shadow-raw transition-[box-shadow] focus:shadow-light-40 dark:focus:shadow-dark-40
    disabled:bg-light-10 dark:disabled:bg-dark-10 disabled:border-none disabled:text-light-50 dark:disabled:text-dark-50`, cls], listeners: { click: onClick } }, [ content ]);
}