<script lang="ts">
import type { Editor, EditorConfiguration, EditorChange } from 'codemirror';
import { changeEnd } from 'codemirror';
import { fromTextArea } from 'hypermd';

import '#shared/hypermd.extend';

function onChange(cm: Editor, change: EditorChange)
{
    if (changeEnd(change).line == cm.lastLine())
        updateBottomMargin(cm);
}


function updateBottomMargin(cm: Editor)
{
    let padding = "";
    if (cm.lineCount() > 1)
    {
        //@ts-ignore
        let totalH = cm.display.scroller.clientHeight - 30, lastLineH = cm.getLineHandle(cm.lastLine()).height;
        padding = (totalH / 2 - lastLineH) + "px";
    }

    if (cm.state.scrollPastEndPadding != padding)
    {
        cm.state.scrollPastEndPadding = padding;
        cm.display.lineSpace.parentNode.style.paddingBottom = padding;
    }
}
</script>

<script setup lang="ts">

const { placeholder, autofocus = false, gutters = true, format = 'd-any' } = defineProps<{
    placeholder?: string
    autofocus?: boolean
    gutters?: boolean
    format?: 'hypermd' | 'd-any'
}>();
const model = defineModel<string>();
const editor = ref<Editor>();

const input = useTemplateRef('input');

onMounted(() => {
    if(input.value)
    {
        const e = editor.value = fromTextArea(input.value, {
            mode: {
                name: format,
                hashtag: true,
                toc: false,
                math: false,
                orgModeMarkup: false,
                tokenTypeOverrides: {
                    hr: "line-HyperMD-hr line-background-HyperMD-hr-bg hr",
                    list1: "list-1",
                    list2: "list-2",
                    list3: "list-3",
                    code: "inline-code",
                    hashtag: "hashtag meta"
                }
            },
            spellcheck: true,
            autofocus: autofocus,
            lineNumbers: false,
            showCursorWhenSelecting: true,
            indentUnit: 4,
            autoCloseBrackets: true,
            foldGutter: gutters,
            theme: 'custom'
        } as EditorConfiguration);

        e.setValue(model.value ?? '');
        updateBottomMargin(e);
        e.on('change', onChange);
        e.on('change', (cm: Editor, change: EditorChange) => model.value = cm.getValue());
        e.on('refresh', updateBottomMargin);
    }
});

watchEffect(() => {
    const value = editor.value?.getValue();
    if (editor.value && model.value !== value) {
        editor.value.setValue(model.value ?? '');
        editor.value.clearHistory();
    }
});
</script>

<template>
    <div :class="{ 'cancel-gutters': !gutters }" class="flex flex-1 w-full justify-stretch items-stretch !font-sans !text-base">
        <textarea ref="input" class="hidden"></textarea>
    </div>
</template>

<style>
.CodeMirror
{
    @apply bg-transparent;
    @apply flex-1 h-full;
    @apply font-sans;

    @apply text-light-100 dark:text-dark-100;
}
.cancel-gutters .CodeMirror-gutters
{
    @apply hidden;
}
.cancel-gutters .CodeMirror-sizer
{
    @apply ms-2;
}
.CodeMirror-gutters
{
    @apply bg-transparent;
    @apply border-transparent;
}
.CodeMirror-gutter-wrapper
{
    @apply absolute top-0 bottom-0;
    @apply flex justify-center items-center;
}
.CodeMirror-foldmarker
{
    @apply text-light-100;
    @apply dark:text-dark-100;
    @apply ps-3;
    text-shadow: none;
}
.hmd-inactive-line .cm-formatting-header, .hmd-inactive-line .cm-formatting-link, .hmd-inactive-line .cm-link-has-alias, .hmd-inactive-line .cm-link-alias-pipe
{
    @apply hidden;
}
.CodeMirror-line 
{
    @apply text-base;
}
.CodeMirror-cursor
{
    @apply border-light-100 dark:border-dark-100;
}
.CodeMirror-selected
{
    @apply bg-light-35 dark:bg-dark-35;
}
.HyperMD-list-line-1 {
    @apply !ps-0;
}
.HyperMD-list-line-2 {
    @apply !ps-6;
}
.HyperMD-list-line-3 {
    @apply !ps-12;
}
</style>