<script setup lang="ts">
import './style/index.scss';
import { message, notification } from 'ant-design-vue';
import type { NotificationArgsProps } from 'ant-design-vue/es/notification';
import type { MessageArgsProps } from 'ant-design-vue/es/message';
import type { EditorEmits, EditorInstance, EditorProps } from './types';
import { useEditor } from './useEditor';
import Preview from './preview.vue';

defineOptions({
  name: 'EditorContainer',
});

const props = defineProps<EditorProps>();
const emits = defineEmits<EditorEmits>();

const lastText = ref('');
const lastContent = ref('');
const [model, modifiers] = defineModel<string, 'html' | 'text'>('content', {
  set(value) {
    return modifiers.text ? lastText : value;
  },
});

const container = useTemplateRef('container');
const preview = useTemplateRef('preview');

const instance = useEditor(container, props, {
  onCreated(editor) {
    emits('created', editor);
    monitor(editor);
  },
  onChange(editor, content) {
    emits('change', editor, content);
    lastText.value = content.text;
    lastContent.value = content.html;
    model.value = content.html;
  },
});

watchEffect(() => {
  if (modifiers.text) return;
  const value = model.value;
  if (instance.editor.value && value != null && value !== unref(lastContent)) {
    instance.editor.value.setHtml(value ?? '');
  }
});

const n = (type: 'info' | 'success' | 'warning' | 'error', payload: NotificationArgsProps) => notification[type]({
  ...payload,
  getContainer: () => (container.value as HTMLElement) ?? document.body,
});
const m = (payload: MessageArgsProps) => message[payload.type ?? 'info'](payload);

function monitor(editor: EditorInstance) {
  editor.on('upload:progress', (event) => n('info', event));
  editor.on('upload:success', (event) => n('success', event));
  editor.on('upload:failed', (event) => n('error', event));
  editor.on('message', (event) => m(event));
  if (props.previewable) editor.on('preview', () => { preview.value?.toggle() });
}

defineExpose(instance);
</script>

<template>
  <div class="editor-container editor-generate-preview-wrapper" ref="container">
    <preview ref="preview" v-if="previewable" :content="lastContent">
      <template #preview-header><slot name="preview-header"></slot></template>
      <template #preview-footer><slot name="preview-footer"></slot></template>
    </preview>
  </div>
</template>

<style scoped lang="scss">
.editor-container {
  display: flex;
  flex-direction: column-reverse !important;
  height: 100%;
  &.editor-generate-preview-wrapper {
    padding: 0 0 1em;
  }
  &.w-e-full-screen-container {
    background-color: #fff;
  }
  &:not(.w-e-full-screen-container) {
    max-height: var(--height, 100%);
    position: relative;
  }
  overflow: hidden;

  :deep(.ant-notification) {
    top: 40px !important;
    position: absolute !important;
  }
}
:deep(.toolbar-container) {
  flex: none;
}
:deep(.content-container) {
  flex: auto;
  overflow-y: auto;
}
</style>
