<template>
  <div
    :dusk="attribute"
    class="bg-white dark:bg-gray-900 rounded-lg"
    :class="{
      'markdown-fullscreen fixed inset-0 z-50 overflow-x-hidden overflow-y-auto':
        isFullScreen,
      'form-input form-control-bordered px-0 overflow-hidden': !isFullScreen,
      'outline-none ring ring-primary-100 dark:ring-gray-700': isFocused,
    }"
    @dragenter.prevent="handleOnDragEnter"
    @dragleave.prevent="handleOnDragLeave"
    @dragover.prevent
    @drop.prevent="handleOnDrop"
  >
    <header
      class="bg-white dark:bg-gray-900 flex items-center content-center justify-between border-b border-gray-200 dark:border-gray-700"
      :class="{
        'fixed top-0 w-full z-10': isFullScreen,
        'bg-gray-100': readonly,
      }"
    >
      <div class="w-full flex items-center content-center">
        <button
          type="button"
          :class="{ 'text-primary-500 font-bold': visualMode === 'write' }"
          @click.stop="setWriteVisualMode"
          class="ml-1 px-3 h-10 focus:outline-none focus:ring ring-primary-200 dark:ring-gray-600"
        >
          {{ __('Write') }}
        </button>
        <button
          v-if="previewer"
          type="button"
          :class="{ 'text-primary-500 font-bold': visualMode === 'preview' }"
          @click.stop="setPreviewVisualMode"
          class="px-3 h-10 focus:outline-none focus:ring ring-primary-200 dark:ring-gray-600"
        >
          {{ __('Preview') }}
        </button>
      </div>

      <MarkdownEditorToolbar
        v-if="!readonly"
        @action="handleAction"
        dusk="markdown-toolbar"
      />
    </header>

    <div
      v-show="visualMode == 'write'"
      @click="isFocused = true"
      class="dark:bg-gray-900"
      :class="{
        'mt-6': isFullScreen,
        'readonly bg-gray-100': readonly,
      }"
      :dusk="isFullScreen ? `markdown-fullscreen-editor` : `markdown-editor`"
    >
      <div class="p-4">
        <textarea ref="theTextarea" :class="{ 'bg-gray-100': readonly }" />
      </div>
      <label
        v-if="uploader"
        @change.prevent="handleFileSelectionClick"
        class="cursor-pointer block bg-gray-100 dark:bg-gray-700 text-gray-400 text-xxs px-2 py-1"
        :class="{ hidden: isFullScreen }"
        :dusk="`${attribute}-file-picker`"
      >
        <span>{{ statusContent }}</span>
        <input
          ref="fileInput"
          type="file"
          class="hidden"
          accept="image/*"
          :multiple="true"
          @change.prevent="handleFileChange"
        />
      </label>
    </div>

    <div
      v-show="visualMode == 'preview'"
      class="prose prose-sm dark:prose-invert overflow-auto max-w-none p-4"
      :class="{ 'mt-6': isFullScreen }"
      :dusk="
        isFullScreen ? `markdown-fullscreen-previewer` : `markdown-previewer`
      "
      v-html="previewContent"
    />
  </div>
</template>

<script setup>
import { onMounted, onBeforeUnmount, useTemplateRef } from 'vue'
import { useDragAndDrop } from '@/composables/useDragAndDrop'
import { useLocalization } from '@/composables/useLocalization'
import { useMarkdownEditing } from '@/composables/useMarkdownEditing'

const { __ } = useLocalization()

const emitter = defineEmits([
  'initialize',
  'change',
  'fileRemoved',
  'fileAdded',
])

const props = defineProps({
  attribute: { type: String, required: true },
  readonly: { type: Boolean, default: false },
  previewer: { type: [Object, Function], required: false, default: null },
  uploader: { type: [Object, Function], required: false, default: null },
})

const {
  createMarkdownEditor,
  isFullScreen,
  isFocused,
  isEditable,
  visualMode,
  previewContent,
  statusContent,
} = useMarkdownEditing(emitter, props)

let markdown = null
const theTextareaRef = useTemplateRef('theTextarea')
const fileInputRef = useTemplateRef('fileInput')

const handleFileSelectionClick = () => fileInputRef.value.click()
const handleFileChange = () => {
  if (props.uploader && markdown.actions) {
    const items = fileInputRef.value.files

    for (let i = 0; i < items.length; i++) {
      markdown.actions.uploadAttachment(items[i])
    }

    fileInputRef.value.files = null
  }
}

const { startedDrag, handleOnDragEnter, handleOnDragLeave } =
  useDragAndDrop(emitter)

const handleOnDrop = e => {
  if (props.uploader && markdown.actions) {
    const items = e.dataTransfer.files

    for (let i = 0; i < items.length; i++) {
      if (items[i].type.indexOf('image') !== -1) {
        markdown.actions.uploadAttachment(items[i])
      }
    }
  }
}

onMounted(() => {
  markdown = createMarkdownEditor(this, theTextareaRef)

  emitter('initialize')
})

onBeforeUnmount(() => markdown.unmount())

const setWriteVisualMode = () => {
  visualMode.value = 'write'
  markdown.actions.refresh()
}

const setPreviewVisualMode = async () => {
  previewContent.value = await props.previewer(markdown.editor.getValue() ?? '')
  visualMode.value = 'preview'
}

const handleAction = action => {
  markdown.actions.handle(this, action)
}

defineExpose({
  setValue(value) {
    if (markdown?.actions) {
      markdown.actions.setValue(value)
    }
  },
  setOption(key, value) {
    if (markdown?.editor) {
      markdown.editor.setOption(key, value)
    }
  },
})
</script>
