<template>
  <div ref="host" class="script-content-editor" />
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount } from 'vue'
import { buildMonacoEditorOptions, initMonaco } from '@/monaco/initMonaco'

import type * as Monaco from 'monaco-editor'

const props = defineProps<{
  modelValue: string
  readonly?: boolean
}>()

const emit = defineEmits<{
  'update:modelValue': [value: string]
}>()

const monaco = initMonaco()
const host = ref<HTMLElement>()
let editor: Monaco.editor.IStandaloneCodeEditor | null = null
let syncing = false

function bindEditor() {
  if (!host.value) return
  editor?.dispose()
  editor = monaco.editor.create(host.value, {
    ...buildMonacoEditorOptions({ language: 'shell', readOnly: props.readonly ?? false }),
    value: props.modelValue || '',
  })
  editor.onDidChangeModelContent(() => {
    if (syncing || !editor) return
    emit('update:modelValue', editor.getValue())
  })
}

watch(
  () => props.modelValue,
  (val) => {
    if (!editor) return
    const current = editor.getValue()
    if (current === val) return
    syncing = true
    editor.setValue(val || '')
    syncing = false
  },
)

watch(
  () => props.readonly,
  (ro) => {
    editor?.updateOptions({ readOnly: ro ?? false })
  },
)

onMounted(() => {
  bindEditor()
})

onBeforeUnmount(() => {
  editor?.dispose()
  editor = null
})
</script>

<style scoped>
.script-content-editor {
  height: 360px;
  border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
  border-radius: 8px;
  overflow: hidden;
}
</style>
