<template>
	<div :style="{ '--editor-height': editorHeight }">
		<ckeditor :editor="editor" v-model="editorData" :config="editorConfig" :disabled="disabled" @blur="onBlur" @focus="onFocus"></ckeditor>
	</div>
</template>

<script setup>
import {
	ClassicEditor,
	Alignment,
	AutoImage,
	Autoformat,
	BlockQuote,
	Bold,
	CodeBlock,
	DataFilter,
	DataSchema,
	Essentials,
	FindAndReplace,
	FontBackgroundColor,
	FontColor,
	FontFamily,
	FontSize,
	GeneralHtmlSupport,
	Heading,
	Highlight,
	HorizontalLine,
	Image,
	ImageCaption,
	ImageInsert,
	ImageResize,
	ImageStyle,
	ImageToolbar,
	ImageUpload,
	Indent,
	IndentBlock,
	Italic,
	Link,
	LinkImage,
	List,
	MediaEmbed,
	MediaEmbedToolbar,
	Mention,
	Paragraph,
	PasteFromOffice,
	RemoveFormat,
	SelectAll,
	ShowBlocks,
	SourceEditing,
	SpecialCharacters,
	SpecialCharactersArrows,
	SpecialCharactersCurrency,
	SpecialCharactersEssentials,
	SpecialCharactersLatin,
	SpecialCharactersMathematical,
	SpecialCharactersText,
	Style,
	Subscript,
	Superscript,
	Table,
	TableCaption,
	TableCellProperties,
	TableColumnResize,
	TableProperties,
	TableToolbar,
	TextTransformation,
	TodoList,
	Underline,
	Undo,
	WordCount,
} from 'ckeditor5'
import { Ckeditor } from '@ckeditor/ckeditor5-vue'
import { UploadAdapterPlugin } from './UploadAdapter.js'

import { ref, computed, watch } from 'vue'
import { useCurrentInstance } from '@/utils/tool'

import coreTranslations from 'ckeditor5/translations/zh-cn.js'
import 'ckeditor5/ckeditor5.css'

const { proxy } = useCurrentInstance()

// 组件名称
defineOptions({
	name: 'scCkeditor',
})

// Props 定义
const props = defineProps({
	modelValue: {
		type: String,
		default: '',
	},
	placeholder: {
		type: String,
		default: '请输入内容……',
	},
	toolbar: {
		type: String,
		default: 'basic',
	},
	height: {
		type: String,
		default: '400px',
	},
	disabled: {
		type: Boolean,
		default: false,
	},
})

// Emits 定义
const emit = defineEmits(['update:modelValue'])

// 工具栏配置常量
const TOOLBARS = {
	full: [
		'sourceEditing',
		'undo',
		'redo',
		'heading',
		'style',
		'|',
		'superscript',
		'subscript',
		'removeFormat',
		'bold',
		'italic',
		'underline',
		'link',
		'fontBackgroundColor',
		'fontFamily',
		'fontSize',
		'fontColor',
		'|',
		'outdent',
		'indent',
		'alignment',
		'bulletedList',
		'numberedList',
		'todoList',
		'|',
		'blockQuote',
		'insertTable',
		'imageInsert',
		'mediaEmbed',
		'highlight',
		'horizontalLine',
		'selectAll',
		'showBlocks',
		'specialCharacters',
		'codeBlock',
		'findAndReplace',
	],
	basic: [
		'sourceEditing',
		'undo',
		'redo',
		'heading',
		'|',
		'removeFormat',
		'bold',
		'italic',
		'underline',
		'link',
		'fontBackgroundColor',
		'fontFamily',
		'fontSize',
		'fontColor',
		'|',
		'outdent',
		'indent',
		'alignment',
		'bulletedList',
		'numberedList',
		'todoList',
		'|',
		'insertTable',
		'imageInsert',
		'mediaEmbed',
	],
	simple: ['undo', 'redo', 'heading', '|', 'removeFormat', 'bold', 'italic', 'underline', 'link', 'fontBackgroundColor', 'fontFamily', 'fontSize', 'fontColor', '|', 'insertTable', 'imageInsert', 'mediaEmbed'],
}

// 插件配置常量
const PLUGINS = [
	Alignment,
	AutoImage,
	Autoformat,
	BlockQuote,
	Bold,
	CodeBlock,
	DataFilter,
	DataSchema,
	Essentials,
	FindAndReplace,
	FontBackgroundColor,
	FontColor,
	FontFamily,
	FontSize,
	GeneralHtmlSupport,
	Heading,
	Highlight,
	HorizontalLine,
	Image,
	ImageCaption,
	ImageInsert,
	ImageResize,
	ImageStyle,
	ImageToolbar,
	ImageUpload,
	Indent,
	IndentBlock,
	Italic,
	Link,
	LinkImage,
	List,
	MediaEmbed,
	MediaEmbedToolbar,
	Mention,
	Paragraph,
	PasteFromOffice,
	RemoveFormat,
	SelectAll,
	ShowBlocks,
	SourceEditing,
	SpecialCharacters,
	SpecialCharactersArrows,
	SpecialCharactersCurrency,
	SpecialCharactersEssentials,
	SpecialCharactersLatin,
	SpecialCharactersMathematical,
	SpecialCharactersText,
	Style,
	Subscript,
	Superscript,
	Table,
	TableCaption,
	TableCellProperties,
	TableColumnResize,
	TableProperties,
	TableToolbar,
	TextTransformation,
	TodoList,
	Underline,
	Undo,
	WordCount,
	UploadAdapterPlugin,
]

// 响应式数据
const editorData = ref('')
const editorHeight = ref(props.height)
const editor = ClassicEditor

// 编辑器配置
const editorConfig = computed(() => ({
	language: { ui: 'zh-cn', content: 'zh-cn' },
	translations: [coreTranslations],
	plugins: PLUGINS,
	toolbar: {
		shouldNotGroupWhenFull: true,
		items: TOOLBARS[props.toolbar] || TOOLBARS.basic,
	},
	placeholder: props.placeholder,
	image: {
		styles: ['alignLeft', 'alignCenter', 'alignRight'],
		toolbar: ['imageTextAlternative', 'toggleImageCaption', '|', 'imageStyle:alignLeft', 'imageStyle:alignCenter', 'imageStyle:alignRight', '|', 'linkImage'],
	},
	mediaEmbed: {
		previewsInData: true,
		providers: [
			{
				name: 'mp4',
				url: /\.(mp4|avi|mov|flv|wmv|mkv)$/i,
				html: (match) => {
					const url = match['input']
					return '<video controls width="100%" height="100%" src="' + url + '"></video>'
				},
			},
		],
	},
	fontSize: {
		options: [10, 12, 14, 16, 18, 20, 22, 24, 26, 30, 32, 36],
	},
	style: {
		definitions: [
			{
				name: 'Article category',
				element: 'h3',
				classes: ['category'],
			},
			{
				name: 'Info box',
				element: 'p',
				classes: ['info-box'],
			},
		],
	},
	upload: {
		uploadUrl: proxy?.$API?.common?.upload?.url || '',
		withCredentials: false,
		extendData: { type: 'images' },
		headers: {
			Authorization: 'Bearer ' + proxy?.$TOOL?.data?.get('TOKEN'),
		},
	},
}))

// 监听 modelValue 变化
watch(
	() => props.modelValue,
	(newVal) => {
		editorData.value = newVal ?? ''
	},
	{ immediate: true },
)

// 监听 height 变化
watch(
	() => props.height,
	(newVal) => {
		editorHeight.value = newVal
	},
)

// 移除图片宽高的正则替换函数
const stripImageDimensions = (html) => {
	return html.replace(/<img[^>]*>/gi, (match) => {
		return match.replace(/width="[^"]*"/gi, '').replace(/height="[^"]*"/gi, '')
	})
}

// 失去焦点事件 - 移除图片的固定宽高，避免响应式布局问题
const onBlur = () => {
	const cleanedData = stripImageDimensions(editorData.value)
	editorData.value = cleanedData
	emit('update:modelValue', cleanedData)
}
</script>

<style>
:root {
	--ck-z-panel: 9999;
}

.ck-content {
	height: var(--editor-height);
}

.ck-source-editing-area,
.ck-source-editing-area textarea {
	height: var(--editor-height);
}

.ck-source-editing-area textarea {
	overflow-y: scroll !important;
}
</style>
