<script setup lang="ts">
import { json } from "@codemirror/lang-json";
import {
  defaultHighlightStyle,
  syntaxHighlighting,
} from "@codemirror/language";
import { EditorState } from "@codemirror/state";
import { basicSetup, EditorView } from "codemirror";

const { codes } = defineProps<{ codes: object | undefined }>();

const emit = defineEmits(["update:codes"]);

const view = ref<EditorView>();

watchEffect(() => {
  if (!view.value) return;
  view.value.dispatch({
    changes: {
      from: 0,
      to: view.value.state.doc.length,
      insert: JSON.stringify(codes, null, 2),
    },
  });
});

onMounted(() => {
  const state = EditorState.create({
    doc: codes ? JSON.stringify(codes, null, 2) : "",
    extensions: [
      basicSetup,
      syntaxHighlighting(defaultHighlightStyle),
      json(),
      EditorState.transactionFilter.of((tr) => {
        if (tr.docChanged) {
          // emit("update:codes", tr.newDoc.toJSON());
          debouncedUpdate(JSON.parse(tr.newDoc.toString()));
        }
        return tr;
      }),
    ],
  });

  view.value = new EditorView({
    parent: document.getElementById("code") as HTMLElement,
    state: state,
  });
});

const debouncedUpdate = useDebounceFn((value: object) => {
  emit("update:codes", value);
}, 1000 * 3);
</script>

<template>
  <div id="code"></div>
</template>

<style scoped>
:global(.cm-editor) {
  height: 100%;
}
</style>
