<template>
    <div v-if="editor" class="note-editor">
        <editor-content :editor="editor" class="editor-wrap" />

        <editor-menu :editor="editor" />
    </div>
</template>

<script setup>
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
import { onBeforeUnmount, onMounted, shallowRef } from 'vue'
import { TaskList, TaskItem } from '@tiptap/extension-list'
import { Highlight } from '@tiptap/extension-highlight'
import { Editor, EditorContent } from '@tiptap/vue-3'
import Document from '@tiptap/extension-document'
import { Placeholder } from '@tiptap/extensions'
import { all, createLowlight } from 'lowlight'
import useNotes from '@/composables/useNotes'
import StarterKit from '@tiptap/starter-kit'
import _debounce from 'lodash/debounce'
import EditorMenu from './Menu.vue'

const props = defineProps({
    id: {
        type: String,
        required: true,
    },
})

const editor = shallowRef()

const { loadNote, updateNote } = useNotes()

const onUpdate = _debounce(async ({ editor }) => {
    const json = editor.getJSON()
    const text = editor.getText()

    // Get doc title
    let title
    const doc = editor.state.doc

    const firstNode = doc.firstChild
    if (!firstNode || firstNode.type.name !== 'heading') title = 'Untitled'

    title = firstNode.textContent.trim() || 'Untitled'

    await updateNote(props.id, {
        title,
        content: json,
        plainText: text,
    })
}, 300)

onMounted(async () => {
    const note = await loadNote(props.id)

    // Lowlight setup
    const lowlight = createLowlight(all)

    // Force note format
    const CustomDocument = Document.extend({
        content: 'heading block*',
    })

    editor.value = new Editor({
        extensions: [
            CustomDocument,
            StarterKit.configure({
                document: false,
                heading: { levels: [1] },
                trailingNode: {
                    node: 'paragraph',
                },
            }),
            Placeholder.configure({
                placeholder: ({ node }) => {
                    if (node.type.name === 'heading') {
                        return 'Title'
                    }
                },
            }),
            TaskList,
            TaskItem,
            Highlight,
            CodeBlockLowlight.configure({
                lowlight,
                enableTabIndentation: true,
            }),
        ],
        content: note.content || [],
        onUpdate: onUpdate,
    })
})
onBeforeUnmount(() => {
    editor.value?.destroy?.()
})
</script>

<style lang="scss">
.note-editor {
    h1 {
        font-weight: 700 !important;
        @include p;

        &:first-child {
            @include drop-cap;
        }
    }
    h1.is-editor-empty:first-child::before {
        color: var(--grey-100);
        content: attr(data-placeholder);
        pointer-events: none;
        @include drop-cap;
    }
    p strong {
        font-weight: 700;
    }
    p em {
        /* font-style: italic; */
        color: var(--grey-100);
    }
    hr {
        border: 1px dashed currentColor;
    }
    ul {
        list-style-type: disc;

        li {
            display: list-item;
            margin-left: 1em;

            *:not(:last-child) {
                margin-bottom: 0.5em;
            }
        }
    }
    ol {
        list-style-type: decimal;

        li {
            display: list-item;
            margin-left: 1.5em;

            &::marker {
                @include p;
            }
        }
    }
    li:not(:last-child) {
        margin-bottom: 0.5em;
    }
    a {
        color: var(--theme-link);
        cursor: pointer;
    }
    code {
        border: 1px solid var(--grey-100);
        color: var(--theme-accent);
        padding: 0 0.2em;
        border-radius: 0.2em;
    }
    pre code {
        display: block;
        color: inherit;
        padding: 1em;

        /* Code styling */
        .hljs-comment,
        .hljs-quote {
            color: #616161;
        }

        .hljs-variable,
        .hljs-template-variable,
        .hljs-attribute,
        .hljs-tag,
        .hljs-name,
        .hljs-regexp,
        .hljs-link,
        .hljs-name,
        .hljs-selector-id,
        .hljs-selector-class {
            color: #f98181;
        }

        .hljs-number,
        .hljs-meta,
        .hljs-built_in,
        .hljs-builtin-name,
        .hljs-literal,
        .hljs-type,
        .hljs-params {
            color: #fbbc88;
        }

        .hljs-string,
        .hljs-symbol,
        .hljs-bullet {
            color: #b9f18d;
        }

        .hljs-title,
        .hljs-section {
            color: #faf594;
        }

        .hljs-keyword,
        .hljs-selector-tag {
            color: #70cff8;
        }

        .hljs-emphasis {
            font-style: italic;
        }

        .hljs-strong {
            font-weight: 700;
        }
    }
    blockquote {
        border-left: 4px solid var(--grey-100);
        padding-left: 0.5em;
    }
    s {
        position: relative;

        &::after {
            content: ' ';
            display: block;
            position: absolute;
            top: 50%;
            left: 0;
            right: 0;
            height: 1px;
            background: currentColor;
        }
    }
    mark {
        background: var(--theme-accent);
        color: var(--theme-bg);
        padding: 0 0.2em;
    }

    ul[data-type='taskList'] {
        list-style: none;
        margin-left: 0;
        padding: 0;

        li {
            align-items: center;
            display: flex;
            margin-left: 0;

            > label {
                flex: 0 0 auto;
                margin-right: 0.5rem;
                user-select: none;
                margin-bottom: 0;

                input {
                    margin: 0;
                }
            }

            > div {
                flex: 1 1 auto;
            }
        }
        input[type='checkbox'] {
            cursor: pointer;
            display: block;
            width: 1.5em;
            height: 1.5em;
            border: 1px solid var(--grey-100);
            border-radius: 0.2em;

            &::after {
                content: '✓';
                font-size: 1.5em;
                opacity: 0;
            }
            &:checked::after {
                opacity: 1;
            }
        }
        ul[data-type='taskList'] {
            margin: 0;
        }
    }

    .editor-wrap {
        > div {
            display: flex;
            flex-direction: column;
            gap: 20px;

            &:focus {
                outline: none;
            }
        }
    }
}
</style>
