<style>
.editor
{
    white-space: pre-line;
    overflow: auto;
    outline: none;
    box-shadow: none !important;
}
</style>

<template>
  <div class="editor" contenteditable>
    <template
      v-if="model && model.length > 0">
      <MarkdownRenderer
        v-if="node"
        :key="key"
        :node="node"
        :proses="{
          'a': LiveA,
          'h1': LiveH1,
          'h2': LiveH2,
          'h3': LiveH3,
          'h4': LiveH4,
          'h5': LiveH5,
          'h6': LiveH6,
          'blockquote': LiveBlockquote,
        }"
      ></MarkdownRenderer>
    </template>
  </div>
</template>

<script setup lang="ts">
import LiveA from "~/components/prose/live/LiveA.vue";
import LiveH1 from "~/components/prose/live/LiveH1.vue";
import LiveH2 from "~/components/prose/live/LiveH2.vue";
import LiveH3 from "~/components/prose/live/LiveH3.vue";
import LiveH4 from "~/components/prose/live/LiveH4.vue";
import LiveH5 from "~/components/prose/live/LiveH5.vue";
import LiveH6 from "~/components/prose/live/LiveH6.vue";
import LiveBlockquote from "~/components/prose/ProseBlockquote.vue";

import { hash } from 'ohash'
import { watch, computed } from 'vue'
import type { Root } from 'hast';
import { diffLines as diff } from 'diff';

const model = defineModel<string>();

const parser = useMarkdown();
const key = computed(() => hash(model.value));

const node = ref<Root>();

watch(model, async (value, old) => {
  if(value && old)
  {
    if(node.value)
    {
      let content = "", line = 0, pos = -1, len = 0, child;
      const d = diff(old, value);
      const children = node.value?.children.filter(e => e.hasOwnProperty('position'));

      for(let i = 0; i < d.length; i++)
      {
        if(d[i].added) //Nouvelle ligne
        {
          const next = d.length > i ? d[i + 1] : undefined;
          if(pos === -1 && (!next || !next.removed)) //Nouvelle ligne
          {
            child = children.filter(e => e.position?.start.line <= line && e.position?.end.line >= line); //Je cherche tout les blocs qui était inclus dans les lignes éditées.
            if(child.length > 0)
            {
              pos = child[0].position?.start.offset ?? 0; //Je pars du premier caractère du bloc
              len += (child[child.length - 1].position?.end.offset ?? 0) + 1; //Je m'arrete au dernier caractère du bloc + le \n
            }
          }
          len += d[i].value.length; // J'ajoute le nouveau nombre de caractère
        }
        else if(d[i].removed) //Ancienne ligne
        {
          child = children.filter(e => e.position?.start.line <= line + 1 && e.position?.end.line >= line + (d[i].count ?? 1)); //Je cherche tout les blocs qui était inclus dans les lignes éditées.
          if(child.length > 0)
          {
            pos = child[0].position?.start.offset ?? 0; //Je pars du premier caractère du bloc
            len += child[child.length - 1].position?.end.offset ?? 0 + 1; //Je m'arrete au dernier caractère du bloc
            len -= d[i].value.length; //Je supprime l'ancien nombre de caractère
          }
        }
        else
        {
          line += d[i].count ?? 0;
        }
      }

      node.value = parser(value);
    }
    else
    {
      node.value = parser(value);
    }
  }
}, { immediate: true });
</script>