<template>
  <div>
    <input
      :id="`${id}_input`"
      :value="initialValue"
      type="hidden"
    />

    <trix-editor
      :id="id"
      ref="trixEditor"
      :input="`${id}_input`"
      class="trix-content"
      v-bind="$attrs"
      @trix-change="onTrixChange"
      @trix-focus="onTrixFocus"
      @trix-blur="onTrixBlur"
      @trix-before-initialize="onTrixBeforeInitialize"
      @trix-initialize="onTrixInitialize"
      @trix-paste="onTrixPaste"
      @trix-selection-change="onTrixSelectionChange"
      @trix-file-accept.prevent="onTrixFileAccept"
      @trix-attachment-add="onTrixAttachmentAdd"
      @trix-attachment-remove="onTrixAttachmentRemove"
    />
  </div>
</template>

<script setup>
import Trix from "trix"

defineOptions({ inheritAttrs: false })

const model = defineModel()

const props = defineProps({
  id: {
    type: String,
    required: false,
    default: () => useId()
  },

  config: {
    type: Object,
    required: false,
    default: () => {}
  }
})

const emit = defineEmits([
  "blur",
  "change",
  "focus",
  "input",
  "trix-attachment-add",
  "trix-attachment-remove",
  "trix-before-initialize",
  "trix-blur",
  "trix-change",
  "trix-file-accept",
  "trix-focus",
  "trix-initialize",
  "trix-paste",
  "trix-selection-change"
])

defineExpose({
  id: props.id,
  modelValue: model,
  reset() {
    reset()
  }
})

const trixEditor = useTemplateRef("trixEditor")
const initialValue = ref(_isNull(model.value) ? "" : model.value)

onBeforeMount(() => {
  _merge(Trix.config, trixConfig, props.config)
})

async function reset() {
  if (_isNull(model.value)) {
    model.value = ""
    await nextTick()
  }

  trixEditor.value?.editor.loadHTML(model.value)
}

function onTrixChange(event) {
  model.value = event.target.value

  emit("change", event)
  emit("input", event)
  emit("trix-change", event)
}

function onTrixInitialize(event) {
  reset()
  emit("trix-initialize", event)
}

function onTrixFocus(event) {
  emit("focus", event)
  emit("trix-focus", event)
}

function onTrixBlur(event) {
  emit("blur", event)
  emit("trix-blur", event)
}

function onTrixBeforeInitialize(event) {
  emit("trix-before-initialize", event)
}

function onTrixPaste(event) {
  emit("trix-paste", event)
}

function onTrixSelectionChange(event) {
  emit("trix-selection-change", event)
}

function onTrixFileAccept(file) {
  emit("trix-file-accept", file)
}

function onTrixAttachmentAdd(file) {
  emit("trix-attachment-add", file)
}

function onTrixAttachmentRemove(file) {
  emit("trix-attachment-remove", file)
}
</script>

<style>
@reference "~/assets/css/main.css";

trix-editor {
  /* textarea.root */
  /* min-height: py-2 [--spacing(4)] + border [2 * 1px = 2px] + line-height [1.5rem] */
  @apply max-w-full! min-h-[calc(--spacing(4)+2px+1.5rem)] appearance-none rounded-md border
  border-surface-300 bg-surface-0 px-3 py-2 text-surface-700
  shadow-[0_1px_2px_0_rgba(18,18,23,0.05)] outline-hidden transition-colors
  duration-200 placeholder:text-surface-500 enabled:hover:border-surface-400
  enabled:focus:border-primary disabled:bg-surface-200 disabled:text-surface-500
  dark:border-surface-700 dark:bg-surface-950 dark:text-surface-0
  dark:placeholder:text-surface-400 dark:enabled:hover:border-surface-600
  dark:disabled:bg-surface-700 dark:disabled:text-surface-400
  p-invalid:border-red-400 p-invalid:placeholder:text-red-600
  dark:p-invalid:border-red-300 dark:p-invalid:placeholder:text-red-400
  p-small:px-2.5 p-small:py-1.5 p-small:text-sm p-large:px-3.5 p-large:py-2.5
  p-large:text-lg p-fluid:w-full p-filled:bg-surface-50
  dark:p-filled:bg-surface-800;
}
</style>
