import { fabric } from 'fabric-with-all'
import { ref, computed } from 'vue'
import { createCanvas } from '../tools/canvasFactory'
import { AnimationManager } from './AnimationManager'
import { detectDeviceType } from '../tools/index'
import { CanvasEventManager } from "./events/CanvasEventManager";
import { OperationType } from '../tools/layerHelper'
import { cloneObjects } from '../tools/canvasMethod'
import { createId } from '../../tools/tools'
import md5 from 'md5'

// 自定义画布转对象属性
fabric.Object.prototype.customProperties = ["top", "left", "width", "height", "scaleX", "scaleY", "info", "thumbnail", "absolutePositioned"];
fabric.Object.prototype.toObject_ = fabric.Object.prototype.toObject
fabric.Object.prototype.toObject = function () {
	const args = [...arguments]
	const arr = [...fabric.Object.prototype.customProperties]
	args.forEach(v => (Array.isArray(v) ? arr.push(...v) : arr.push(v)))
	if (this.fill?.source === null) {
		const image = new Image()
		image.crossOrigin = 'anonymous'
		image.src = this.info?.fill?.source
		this.fill.source = image
	}
	const object = this.toObject_(arr)
	if (object.info) {
		let lock = !!object.info.lock
		if (object.type === "group") lock = true
		object.evented = !lock
		object.selectable = !lock
	}
	return object
}

interface CanvasInitOptions {
	canvasRef: any
	canvasViewWidth?: number
	canvasViewHeight?: number
	canvasWidth?: number
	canvasHeight?: number
	url?: string
}
export class CanvasManager {
	stateManager: any
	layerManager: any
	animationManager: any
	eventManager: any
	deviceInfo: any
	canvas: any
	currentZoom: any
	uniqueId: string
	constructor(options) {
		this.stateManager = options.stateManager;
		this.uniqueId = md5(options.props.config.url || Date.now());
		this.deviceInfo = detectDeviceType();
		this.currentZoom = ref(100)
	}
	onMounted() { }
	getCanvasSize() {
		return {
			canvasViewWidth: this.canvas.width,
			canvasViewHeight: this.canvas.height,
			canvasWidth: this.canvas.clipPath.width,
			canvasHeight: this.canvas.clipPath.height,
		}
	}
	setCanvasViewSize(options) {
		const canvasViewWidth = options.canvasViewWidth || 1920
		const canvasViewHeight = options.canvasViewHeight || 1080
		this.canvas.setWidth(canvasViewWidth)
		this.canvas.setHeight(canvasViewHeight)
	}
	/** 初始化画布 */
	async initCanvas(options: CanvasInitOptions) {
		this.layerManager = this.stateManager.layerManager
		let canvasWidth = options.canvasWidth || 750
		let canvasHeight = options.canvasHeight || 600
		let image = null;
		if (options.url) {
			await new Promise((resolve) => {
				fabric.Image.fromURL(options.url, async (img) => {
					canvasWidth = img.width
					canvasHeight = img.height
					img.set({
						left: 0,
						top: 0,
						scaleX: 1,
						scaleY: 1,
						evented: false,
						selectable: false,
						info: {
							id: createId("image"),
							name: "图片图层",
							lock: true,
							isOriginal: true,
						}
					})
					image = img
					resolve(img)
				}, { crossOrigin: 'anonymous' })
			})
		}
		this.canvas = createCanvas(options.canvasRef.value, {
			backgroundColor: '#fff',
		})
		if (image) {
			this.canvas.add(image)
			await this.layerManager.updateLayerThumbnailsById(image.info.id)
		}
		this.setCanvasViewSize(options)

		this.canvas.clipPath = new fabric.Rect({
			left: 0,
			top: 0,
			width: canvasWidth,
			height: canvasHeight
		})

		// 动画管理器
		this.animationManager = new AnimationManager(this.canvas, {
			currentZoom: this.currentZoom,
			canvasManager: this,
			wheelThrottleTime: 15, // 降低滚轮事件节流时间，提高响应性
			defaultEase: "power2.lin",
			defaultDuration: 0.3, // 缩短默认动画时间
		});

		this.setupCanvasEvents()
		this.setupBrushEvents()

		/** 测试-开始 */
		// this.stateManager.setIsRecord(false)
		// const groupObject = await this.layerManager.createGroupLayer()
		// const parentId = groupObject.info.id
		// const rect = await this.layerManager.createRectLayer({ left: 200, info: { parentId } })
		// const star = await this.layerManager.createStarLayer({ left: 400, info: { parentId } })
		// const arrow = await this.layerManager.createArrowLayer({ left: 600, info: { parentId } })
		// await this.layerManager.createGroupLayer()
		// this.layerManager.setActiveID(rect.info.id)
		// this.stateManager.setIsRecord(true)
		/** 测试-结束 */

		this.resetZoom(false, true)// 画布居中

		this.stateManager.toolManager.setTool(OperationType.SELECT)
		this.layerManager.updateLayers()
		this.stateManager.recordState()
	}
	/** 画布添加对象 */
	async add(obj: any, isRecord = true) {
		this.canvas.add(obj)
		const id = obj?.info?.id || ""
		if (id) {
			this.sortActiveObject(obj)
			await this.layerManager.updateLayers(!!obj.info.parentId)
			this.renderAll()
			await this.layerManager.updateLayerThumbnailsById(id)
		}
		if (isRecord) this.stateManager.recordState()
	}
	/** 画布移除对象 */
	remove(obj: any, isUpdate = true) {
		this.canvas.remove(obj)
		if (isUpdate) {
			this.layerManager.updateLayers()
			this.renderAll()
		}
	}
	/** 根据激活对象排序当前对象 */
	async sortActiveObject(object: any) {
		const activeID = this.layerManager.activeID.value;
		if (!activeID) return
		const activeObject = this.getObjectById(activeID)
		if (!activeObject) return
		if (object.type !== "group") {
			const parentId = activeObject.info?.parentId
			if (!object.info.parentId) object.info.parentId = parentId
		}
		const index = this.getObjects().indexOf(activeObject)
		this.canvas.moveTo(object, index + 1)
		// await this.sortObjectByIds(ids, isRecord)
	}


	/** 更新子图层裁剪区域 */
	async updateSubLayerClipPath() {
		const objects = this.getObjects().filter((v: any) => v.type !== "group" && !!v.info?.id);
		for (let i = 0; i < objects.length; i++) {
			const object = objects[i]
			const path = this.getObjectById(object.info.parentId)?.clipPath
			object.set({ clipPath: path || null })
		}
		this.renderAll()
	}
	/** 排序画布对象 */
	async sortObjectByIds(ids: string[], isRecord?: boolean) {
		ids.forEach((id, index) => {
			this.canvas.moveTo(this.getObjectById(id), index)
		})
		await this.updateSubLayerClipPath()
		this.renderAll()
		if (isRecord) this.stateManager.recordState()
	}


	/** 设置画布事件 */
	setupCanvasEvents() {
		// 创建画布事件管理器
		this.eventManager = new CanvasEventManager(this.canvas, {
			canvasManager: this,
			animationManager: this.animationManager,
			toolManager: this.stateManager.toolManager,
			layerManager: this.stateManager.layerManager,
			stateManager: this.stateManager,
		});
		// 设置动画交互效果
		this.animationManager.setupInteractionAnimations();
	}
	/** 设置激活对象 */
	setActiveObjectById(id: string) {
		this.discardActiveObject()
		const obj = this.getObjectById(id)
		if (!obj) return
		if (obj.type === "group") {
			obj._originPosition = {
				top: obj.top,
				left: obj.left,
				cpTop: obj.clipPath.top,
				cpLeft: obj.clipPath.left,
			}
			const objects = [obj];
			this.getObjects().forEach((item: any) => {
				if (item?.info?.parentId === id) objects.push(item)
			})
			if (objects.length > 0) this.canvas.setActiveObject(new fabric.ActiveSelection(objects, { canvas: this.canvas }));
		} else {
			if (obj.evented) this.canvas.setActiveObject(obj)
		}
		this.renderAll()
	}
	resetZoom(animated = true, adaptive = true) {
		this.animationManager.resetZoom(animated, adaptive)
	}
	// 使用动画管理器的缩放方法
	animateZoom(point, targetZoom, options = {}) {
		this.animationManager.animateZoom(point, targetZoom, options);
	}
	zoomIn() {
		const currentZoom = this.canvas.getZoom()
		const newZoom = Math.min(currentZoom + 0.1, 20) // 增加20%，最大20倍
		// 使用画布中心作为缩放点
		const centerPoint = {
			x: this.canvas.width / 2,
			y: this.canvas.height / 2
		}
		this.animateZoom(centerPoint, newZoom)
	}

	zoomOut() {
		const currentZoom = this.canvas.getZoom()
		const newZoom = Math.max(currentZoom - 0.1, 0.1) // 减少20%，最小0.1倍
		// 使用画布中心作为缩放点
		const centerPoint = {
			x: this.canvas.width / 2,
			y: this.canvas.height / 2
		}
		this.animateZoom(centerPoint, newZoom)
	}
	getObjects() {
		return this.canvas.getObjects() || []
	}
	getObjectById(id: string) {
		return this.getObjects().find((item: any) => item?.info?.id === id)
	}
	getChildObjectsById(id: string) {
		return this.getObjects().filter((item: any) => item?.info?.parentId === id)
	}
	/** 获取选中对象 */
	getSelectedObject() {
		return this.canvas.getActiveObject()
	}
	renderAll() {
		this.canvas.renderAll()
	}
	deleteObjectById(id: string, isUpdate = true) {
		const object = this.getObjectById(id)
		if (object) {
			this.canvas.remove(object)
			if (isUpdate) this.layerManager.updateLayers()
			this.renderAll()
		}
	}
	/** 取消选中对象 */
	discardActiveObject() {
		this.canvas.discardActiveObject()
		this.renderAll()
	}

	/** 画笔事件 */
	setupBrushEvents() {
		this.canvas.onBrushImageConverted = async (fabricImage) => {
			const currentTool = this.stateManager.toolManager.currentTool.value;
			if (currentTool === OperationType.DRAW) {
				this.handleDrawImage(fabricImage)
			} else if (currentTool === OperationType.AISELECT_DRAW) {
				this.stateManager.aiSelectboxToolManager.handleDrawImage(fabricImage)
			}
			return true
		};
	}
	/** 处理绘制图像 */
	async handleDrawImage(fabricImage: fabric.Object) {
		const activeID = this.stateManager.layerManager.activeID.value
		const activeLayer = this.getObjectById(activeID)
		if (activeLayer && activeLayer.fill?.repeat !== "repeat" && activeLayer.type !== "group") {
			this.layerManager.imageMergeToLayer(activeLayer, fabricImage)
		} else {
			const emptyLayer = await this.layerManager.createEmptyLayer(false);
			this.layerManager.setActiveID(emptyLayer.info.id, false)
			this.layerManager.imageMergeToLayer(emptyLayer, fabricImage)
		}
		return true
	}

	/** 导出画布为JSON */
	getCanvasJSON() {
		const json = this.canvas.toJSON()
		return JSON.stringify(json)
	}
	/** 加载画布JSON */
	loadJSON(json: string, rerecord = true) {
		return new Promise((resolve) => {
			let jsonObj = null;
			try {
				jsonObj = JSON.parse(json)
			} catch (error) {
				console.error('JSON解析错误:', error)
			}
			if (!jsonObj) return resolve(false)
			if (jsonObj.uniqueId) this.uniqueId = jsonObj.uniqueId
			this.canvas.loadFromJSON(jsonObj, () => {
				if (rerecord) this.stateManager.clearState()
				this.resetZoom(false)
				this.layerManager.updateLayers()
				this.renderAll()
				if (rerecord) this.stateManager.recordState()

				resolve(true)
			})
		})
	}
	/** 导出画布为处理图片的JSON */
	getCanvasDisUrlJSON() {
		const canvas = this.canvas.toJSON()
		const images = {};
		const create = (url, key) => {
			const key_ = `xxxxx_${this.uniqueId}_${md5(key)}_xxxxx`;
			images[key_] = url
			return key_
		}
		canvas.uniqueId = this.uniqueId
		canvas.objects.forEach((object: any) => {
			const id = object.info?.id
			if (object.thumbnail) {
				object.thumbnail = create(object.thumbnail, `thumbnail_${id}`)
			}
			if (object.src) {
				object.src = create(object.src, `src_${id}`)
				object.crossOrigin = 'anonymous'
			}
			if (object.fill?.source) {
				object.fill.source = create(object.fill.source, `fillsource_${id}`)
			}
			if (object.info?.fill?.source) {
				object.info.fill.source = create(object.info.fill.source, `infofillsource_${id}`)
			}
		})
		return { canvas: JSON.stringify(canvas), images }
	}
	/** 处理JSON为正常画布 */
	processCanvasDisUrlJSON(obj: { canvas: string, images: Object }) {
		let json = obj.canvas;
		const images = obj.images || {}
		for (const key in images) {
			json = json.replace(new RegExp(key), images[key])
		}
		return json
	}
	dispose() {
		this.animationManager?.dispose()
		this.eventManager?.dispose()
	}
}
