<template>
	<div class="depth-canvas">
		<div class="canvas-container" ref="canvasContainerRef">
			<canvas ref="canvasRef"></canvas>
		</div>
		<template v-if="isReady">
			<layer-panel />
			<details-panel />
			<brush-control-panel :currentTool="toolManager.currentTool.value" />
			<ai-selectbox-panel :currentTool="toolManager.currentTool.value" />
			<depth-header-tools @export="exportCanvas" @workbench="onWorkbench" />

			<zoom
				:zoom="canvasManager.currentZoom.value / 100"
				is-home
				@home="() => canvasManager.resetZoom()"
				@add="() => canvasManager.zoomIn()"
				@sub="() => canvasManager.zoomOut()"
			/>
		</template>
	</div>
</template>

<script setup lang="ts">
	import { fabric } from 'fabric-with-all'
	import { computed, ref, markRaw, onMounted, nextTick, provide, onBeforeUnmount } from 'vue'
	import { OperationType } from './tools/layerHelper'
	import { exportCanvasToImage } from './tools/exportMethod'
	// 组件
	import layerPanel from './components/layer-panel/index.vue'
	import detailsPanel from './components/details-panel/index.vue'
	import depthHeaderTools from './components/depth-header-tools.vue'
	import zoom from '../components/zoom.vue'
	import brushControlPanel from './components/brush-control-panel.vue'
	import aiSelectboxPanel from './components/ai-selectbox-panel.vue'

	// 管理器
	import { StateManager } from './manager/StateManager'
	import { LayerManager } from './manager/LayerManager'
	import { CanvasManager } from './manager/CanvasManager'
	import { ToolManager } from './manager/ToolManager'
	import { KeyEventManager } from './manager/events/KeyEventManager'
	import { ObjectManager } from './manager/ObjectManager'

	import { useGlobalStore } from '@/stores'
	const globalStore = useGlobalStore()

	const emit = defineEmits(['workbench', 'close'])
	const props = defineProps({
		config: {
			type: Object,
			default: () => ({})
		}
	})
	const onWorkbench = async () => {
		if (stateManager.historyIndex.value === 0) {
			emit('close')
		} else {
			exportCanvasToImage(canvasManager.canvas).then((url) => {
				const { canvas, images } = canvasManager.getCanvasDisUrlJSON()
				emit('workbench', { url, canvas, images })
			})
		}
	}

	// 准备就绪
	const isReady = ref(false)
	const canvasContainerRef = ref(null)
	const canvasRef = ref(null)

	// 状态管理器
	const stateManager = new StateManager({})
	provide('stateManager', stateManager)

	// 画布管理器
	const canvasManager = new CanvasManager({ stateManager, props })
	stateManager.setManager({ canvasManager })
	provide('canvasManager', canvasManager)

	// 图层管理器
	const layerManager = new LayerManager({ stateManager, canvasManager })
	stateManager.setManager({ layerManager })
	provide('layerManager', layerManager)

	// 工具管理器
	const toolManager = new ToolManager({ stateManager, canvasManager })
	stateManager.setManager({ toolManager })
	provide('toolManager', toolManager)

	//键盘事件管理器
	const keyEventManager = new KeyEventManager({ stateManager, onWorkbench, layerManager })
	stateManager.setManager({ keyEventManager })
	provide('keyEventManager', keyEventManager)

	// 对象管理器
	const objectManager = new ObjectManager({ stateManager, canvasManager, layerManager })
	stateManager.setManager({ objectManager })
	provide('objectManager', objectManager)

	const observer = ref(null)
	onMounted(async () => {
		globalStore.setLoading(true)
		keyEventManager.registerEvents()
		const url = props.config.url || ''
		const canvasData = props.config.canvasData || ''
		await canvasManager.initCanvas({
			canvasRef,
			canvasViewWidth: canvasContainerRef.value.clientWidth,
			canvasViewHeight: canvasContainerRef.value.clientHeight,
			canvasWidth: props.config.width || 750,
			canvasHeight: props.config.height || 600,
			url: canvasData ? '' : url
		})
		if (canvasData) {
			const json = canvasManager.processCanvasDisUrlJSON(canvasData)
			await canvasManager.loadJSON(json)
		}
		layerManager.setActiveFirstLayer()
		globalStore.setLoading(false)

		stateManager.onMounted()
		canvasManager.onMounted()
		layerManager.onMounted()
		toolManager.onMounted()
		keyEventManager.onMounted()
		objectManager.onMounted()

		const trailingTimeout = ref(null)
		observer.value = new ResizeObserver((entries) => {
			clearTimeout(trailingTimeout.value)
			trailingTimeout.value = setTimeout(async () => {
				handleWindowResize()
			}, 100)
		})
		observer.value.observe(canvasContainerRef.value)

		isReady.value = true // 准备就绪
	})
	onBeforeUnmount(() => {
		observer.value.disconnect()
		canvasManager.dispose()
		stateManager.dispose()
		layerManager.dispose()
		toolManager.dispose()
		keyEventManager.dispose()
		objectManager.dispose()
	})
	async function handleWindowResize() {
		console.log('==========画布窗口大小变化==========')
		canvasManager.setCanvasViewSize({
			canvasViewWidth: canvasContainerRef.value.clientWidth,
			canvasViewHeight: canvasContainerRef.value.clientHeight
		})
		canvasManager.resetZoom(true, true)
	}
	/** 导入本地图片 */
	const importLocalImage = (isRecord = true) => {
		return new Promise((resolve, reject) => {
			const input = document.createElement('input')
			input.type = 'file'
			input.accept = 'image/*'
			input.click()
			input.addEventListener('change', (e: any) => {
				const file = e.target.files[0]
				if (!file) return
				layerManager.createFileImageLayer(file, isRecord).then((v) => resolve(v))
			})
		})
	}
	provide('importLocalImage', importLocalImage)

	const exportCanvas = () => {
		// 导出图片
		exportCanvasToImage(canvasManager.canvas).then((url) => {
			const a = document.createElement('a')
			a.href = url
			a.download = 'canvas.png'
			a.click()
		})

		// console.log(canvasManager.getCanvasJSON())

		// const object = canvasManager.getCanvasDisUrlJSON()
		// console.log(object)
		// const canvas = canvasManager.processCanvasDisUrlJSON(object)
		// console.log(canvas)
	}

	defineExpose({
		onWorkbench
	})
</script>
<style lang="less">
	@import '@vue-flow/core/dist/style.css';
	@import '@vue-flow/core/dist/theme-default.css';
</style>
<style lang="less" scoped>
	.depth-canvas {
		position: relative;
		width: 100%;
		height: 100%;
		user-select: none;
		> .canvas-container {
			position: absolute;
			top: 0;
			left: 0;
			width: 100%;
			height: 100%;
			> canvas {
				width: 100%;
				height: 100%;
			}
			&:deep(.canvas-container) {
				filter: drop-shadow(0 0 5px rgba(0, 0, 0, 0.3));
			}
		}
	}
</style>
