import { ref } from 'vue'
import { fabric } from 'fabric-with-all'
import { createId } from '../../tools/tools'
import { exportObjectsToImage, exportObjectToThumbnail } from '../tools/exportMethod'
import { OperationType, BlendMode } from '../tools/layerHelper'
import { getArrowPath, getLinePath, cloneObjects, getStarArr } from '../tools/canvasMethod'
import i18n from '@/lang/index'
const t = i18n.global.t

export class LayerManager {
	stateManager: any
	canvasManager: any
	layers: any
	activeID: any
	constructor(options) {
		this.stateManager = options.stateManager;
		this.canvasManager = options.canvasManager;
		this.layers = ref([])
		this.activeID = ref("")
	}
	onMounted() { }
	setActiveID(id: string, isActive = true) {
		const layer = this.getLayerById(id)
		// if (layer?.type === "group") {
		// 	this.activeID.value = ""
		// } else {
		this.activeID.value = id
		// }
		if (isActive) {
			this.canvasManager.setActiveObjectById(id)
			this.stateManager.toolManager.setTool(OperationType.SELECT)
		}
	}
	setActiveFirstLayer() {
		const layer = this.layers.value[0]
		const id = layer.type === "group" ? layer.children[0]?.info?.id : layer.info?.id
		this.setActiveID(id || "")
	}

	// 更新图层列表
	async updateLayers(isSort = false) {
		const objects = this.canvasManager.getObjects().map(v => v.toObject()).filter(v => !!v.info?.id).reverse()
		objects.forEach(v => {
			if (v.type === "group") {
				if (!v.children) v.children = []
				return;
			}
			const parentId = v.info?.parentId
			if (!parentId) return
			objects.forEach((obj: any) => {
				if (obj.info?.id !== parentId) return
				if (!obj.children) obj.children = []
				obj.children.push(v)
			})
		})
		const layers = objects.filter(v => !v.info?.parentId)
		this.layers.value = layers
		if (isSort) await this.sortLayers()
	}

	getActiveLayer() {
		return this.getLayerById(this.activeID.value)
	}
	getLayerById(id) {
		function call(arr) {
			for (let i = 0; i < arr.length; i++) {
				const v = arr[i]
				if (v.info.id === id) return v
				if (v.children) {
					const layer = call(v.children)
					if (layer) return layer
				}
			}
			return null
		}
		return call(this.layers.value)
	}
	setLayerNameById(id, name: string) {
		const layer = this.getLayerById(id)
		if (layer) {
			layer.info.name = name
		}
		const object = this.canvasManager.getObjectById(id)
		if (object) {
			object.info.name = name
			this.canvasManager.renderAll()
		}
	}

	/** 设置图层显示状态 */
	setLayerVisibleById(id, visible: boolean) {
		const layer = this.getLayerById(id)
		const object = this.canvasManager.getObjectById(id)
		const call = (layer, object) => {
			if (!layer || !object) return
			layer.visible = visible
			object.set({
				visible: visible
			})
		}
		call(layer, object)
		if (object.type === "group") {
			const children = this.canvasManager.getChildObjectsById(id)
			children.forEach(v => {
				const layer = this.getLayerById(v.info.id)
				call(layer, v)
			})
		}
		this.canvasManager.renderAll()
		this.stateManager.recordState()
	}
	/** 设置图层锁定状态 */
	setLayerLockById(id, lock: boolean) {
		const layer = this.getLayerById(id)
		const object = this.canvasManager.getObjectById(id)
		const call = (layer, object) => {
			if (!layer || !object) return
			layer.info.lock = !!lock
			layer.evented = !lock
			object.info.lock = !!lock
			if (object.type !== "group") {
				object.set({
					evented: !lock,
					selectable: !lock,
				})
			}
		}
		call(layer, object)
		if (object.type === "group") {
			const children = this.canvasManager.getChildObjectsById(id)
			children.forEach(v => {
				const layer = this.getLayerById(v.info.id)
				call(layer, v)
			})
		}
		if (lock) {
			// 取消选中对象
			const e = this.canvasManager.getSelectedObject()
			if (e) {
				const objects = [...(e._objects || [e])]
				if (objects.some(v => v.info?.id === object.info.id)) {
					this.canvasManager.discardActiveObject()
				}
			}
		}
		this.canvasManager.renderAll()
		this.stateManager.recordState()
	}

	/** 删除指定图层 */
	deleteLayerById(id, isActive = true) {
		const layer = this.getLayerById(id)
		if (layer.children) {
			layer.children.forEach(v => this.canvasManager.deleteObjectById(v.info.id, false))
		}
		this.canvasManager.deleteObjectById(id)
		if (id === this.activeID.value && isActive) {
			this.setActiveID(this.layers.value[0]?.info?.id || "")
		}
		if (isActive) this.stateManager.recordState()
	}
	/** 复制指定图层 */
	copyLayerById(id) {
		const object = this.canvasManager.getObjectById(id)
		if (!object) return console.warn('复制图层失败，对象不存在ID:', id)
		this.canvasManager.discardActiveObject()
		cloneObjects([object]).then(objects => {
			const newObject = objects[0]
			const info = JSON.parse(JSON.stringify(newObject.info))
			info.id = createId("copylayer")
			// info.name = info.name
			newObject.set({
				top: newObject.top + 15,
				left: newObject.left + 15,
				info: info,
			})
			this.canvasManager.add(newObject)
			this.setActiveID(newObject.info.id)
		})
	}
	/** 根据layers排序图层 */
	async sortLayers(isRecord?: boolean) {
		const ids = [];
		call(this.layers.value)
		await this.canvasManager.sortObjectByIds(ids.reverse(), isRecord)
		function call(arr) {
			arr.forEach(v => {
				ids.push(v.info.id)
				if (v.children) call(v.children)
			})
		}
	}


	/** 设置图层位置-不设置默认居中 */
	setLayerPosition(object, options?: any) {
		const width = this.canvasManager.canvas.clipPath.width
		const height = this.canvasManager.canvas.clipPath.height

		if (options && options.top !== undefined) {
			object.set({ top: options.top })
		} else {
			object.set({ top: height / 2 - object.height * object.scaleY / 2 })
		}
		if (options && options.left !== undefined) {
			object.set({ left: options.left })
		} else {
			object.set({ left: width / 2 - object.width * object.scaleX / 2 })
		}
	}
	/** 创建空图层 */
	async createEmptyLayer(isRecord = true, isActive = false) {
		const emptyObject = new fabric.Rect({
			width: 0,
			height: 0,
			fill: 'transparent',
			info: {
				id: createId("image"),
				name: t('DepthCanvas.emptyLayer'),
			}
		})
		this.setLayerPosition(emptyObject)
		await this.canvasManager.add(emptyObject, isRecord)
		if (isActive) this.setActiveID(emptyObject.info.id, false)
		return emptyObject
	}
	/** 创建组图层 */
	async createGroupLayer(options?: any, isRecord = true, isActive = false) {
		const groupObject = new fabric.Group([], {
			...(options || {}),
			width: 1,
			height: 1,
			hasControls: false, // 不显示控制点
			hasBorders: false, // 不显示边框
			selectable: false, // 不可选中（可选）
			evented: false,
			info: {
				id: createId("group"),
				name: t('DepthCanvas.aiGroupLayer'),
				showChildren: true,
				...(options?.info || {}),
			}
		})
		this.setLayerPosition(groupObject, options)
		await this.canvasManager.add(groupObject, isRecord)
		if (isActive) this.setActiveID(groupObject.info.id, false)
		return groupObject
	}

	/** 创建文本图层 */
	async createTextLayer(text: string, options?: any) {
		const textObject = new fabric.IText(text, {
			fontSize: 24,
			fill: '#000',
			...(options || {}),
			info: {
				id: createId("text"),
				name: t('DepthCanvas.textLayer'),
				...(options?.info || {}),
			}
		})
		this.setLayerPosition(textObject, options)
		await this.canvasManager.add(textObject)
		return textObject
	}
	/** 创建矩形图层 */
	async createRectLayer(options?: any, isRecord = true, isActive = true) {
		const rectObject = new fabric.Rect({
			width: 100,
			height: 100,
			fill: '#000',
			strokeWidth: 0,
			...(options || {}),
			info: {
				id: createId("rect"),
				name: t('DepthCanvas.rectLayer'),
				...(options?.info || {}),
			}
		})
		this.setLayerPosition(rectObject, options)
		await this.canvasManager.add(rectObject, isRecord)
		if (isActive) this.setActiveID(rectObject.info.id, false)
		return rectObject
	}
	/** 创建直线图层 */
	async createLineLayer(options?: any, isRecord = true, isActive = true) {
		const width = options?.width || 100
		const height = options?.height || 2
		delete options.width
		delete options.height
		const arrowObject = new fabric.Path(getLinePath(width, height), {
			stroke: '#000',    // 只设置边框颜色
			strokeWidth: 2,  // 边框宽度
			fill: 'transparent',  // 不填充
			strokeLineCap: 'round',
			strokeLineJoin: 'round',
			...(options || {}),
			info: {
				id: createId("line"),
				name: t('DepthCanvas.lineLayer'),
				...(options?.info || {}),
			}
		});
		this.setLayerPosition(arrowObject, options)
		await this.canvasManager.add(arrowObject, isRecord)
		if (isActive) this.setActiveID(arrowObject.info.id, false)
		return arrowObject
	}
	/** 创建椭圆图层 */
	async createEllipseLayer(options?: any, isRecord = true, isActive = true) {
		const ellipseObject = new fabric.Ellipse({
			fill: '#000',
			strokeWidth: 0,
			...(options || {}),
			info: {
				id: createId("ellipse"),
				name: t('DepthCanvas.ellipseLayer'),
				...(options?.info || {}),
			}
		})
		this.setLayerPosition(ellipseObject, options)
		await this.canvasManager.add(ellipseObject)
		if (isActive) this.setActiveID(ellipseObject.info.id, false)
		return ellipseObject
	}
	/** 创建三角形图层 */
	async createTriangleLayer(options?: any, isRecord = true, isActive = true) {
		const triangleObject = new fabric.Triangle({
			width: 100,
			height: 100,
			fill: '#000',
			strokeWidth: 0,
			...(options || {}),
			info: {
				id: createId("triangle"),
				name: t('DepthCanvas.triangleLayer'),
				...(options?.info || {}),
			}
		})
		this.setLayerPosition(triangleObject, options)
		await this.canvasManager.add(triangleObject, isRecord)
		if (isActive) this.setActiveID(triangleObject.info.id, false)
		return triangleObject
	}
	/** 创建五角星图层 */
	async createStarLayer(options?: any, isRecord = true, isActive = true) {
		const width = options?.width || 100
		const height = options?.height || 100
		delete options.points
		const starObject = new fabric.Polygon(getStarArr(width, height), {
			type: "star",
			fill: '#000',
			strokeWidth: 0,
			...(options || {}),
			info: {
				id: createId("star"),
				name: t('DepthCanvas.starLayer'),
				...(options?.info || {}),
			}
		})
		this.setLayerPosition(starObject, options)
		await this.canvasManager.add(starObject, isRecord)
		if (isActive) this.setActiveID(starObject.info.id, false)
		return starObject
	}
	/** 创建箭头图层 */
	async createArrowLayer(options?: any, isRecord = true, isActive = true) {
		const width = options?.width || 100
		const strokeWidth = options?.strokeWidth || 4
		delete options.width
		delete options.strokeWidth
		const arrowObject = new fabric.Path(getArrowPath(width, strokeWidth), {
			stroke: '#000',        // 只设置边框颜色
			strokeWidth,       // 边框宽度
			fill: 'transparent',  // 不填充
			strokeLineCap: 'round',
			strokeLineJoin: 'round',
			...(options || {}),
			info: {
				id: createId("arrow"),
				name: t('DepthCanvas.arrowLayer'),
				...(options?.info || {}),
			}
		});
		this.setLayerPosition(arrowObject, options)
		await this.canvasManager.add(arrowObject, isRecord)
		if (isActive) this.setActiveID(arrowObject.info.id, false)
		return arrowObject
	}



	/** 创建图片图层 */
	async createImageLayer(imgOrUrl: string | HTMLImageElement, options?: any, isRecord = true, isActive = true) {
		const { canvasWidth, canvasHeight } = this.canvasManager.getCanvasSize();

		const imageObject = await new Promise((resolve) => {
			const url = typeof imgOrUrl === 'string' ? imgOrUrl : imgOrUrl.src
			fabric.Image.fromURL(url, (img) => {
				const width = img.width
				const height = img.height
				const scaleX = width > canvasWidth ? canvasWidth * 0.8 / width : 1
				const scaleY = height > canvasHeight ? canvasHeight * 0.8 / height : 1
				const scale = Math.min(scaleX, scaleY)
				img.set({
					scaleX: scale,
					scaleY: scale,
					...(options || {}),
					info: {
						id: createId("image"),
						name: t('DepthCanvas.imageLayer'),
						...(options?.info || {}),
					}
				})
				resolve(img)
			})
		}) as fabric.Object
		this.setLayerPosition(imageObject, options)
		await this.canvasManager.add(imageObject, isRecord)
		if (isActive) this.setActiveID(imageObject.info.id)
		return imageObject
	}
	createFileImageLayer(file: File, isRecord = true) {
		return new Promise((resolve) => {
			const reader = new FileReader()
			reader.readAsDataURL(file)
			reader.onload = () => {
				this.stateManager.toolManager.setTool(OperationType.SELECT)
				const url = reader.result as string
				this.createImageLayer(url, { info: { name: file.name } }, isRecord)
					.then((v) => resolve(v))
			}
		})
	}

	/** 合并图层 */
	async imageMergeToLayer(targetLayer: fabric.Object, fabricImage: fabric.Object) {
		const info = await exportObjectsToImage([targetLayer, fabricImage], true)
		const mergedImage = await new Promise((resolve) => {
			fabric.Image.fromURL(info.url, (img) => {
				img.set({
					left: info.left,
					top: info.top,
					info: {
						...(targetLayer?.info || {}),
						id: createId("image"),
						name: targetLayer?.info?.name || t('DepthCanvas.mergeLayer'),
					}
				})
				resolve(img)
			}, { crossOrigin: 'anonymous' })
		})
		const index = this.canvasManager.getObjects().indexOf(targetLayer);
		this.deleteLayerById(targetLayer.info.id, false)

		const nid = mergedImage.info.id
		await this.canvasManager.add(mergedImage, false);
		this.setActiveID(nid, false)
		this.canvasManager.canvas.moveTo(mergedImage, index);

		// this.stateManager.objectManager.setBlendMode(nid, BlendMode.MULTIPLY)
		// this.stateManager.objectManager.setFillRepeat(nid, false)

		this.canvasManager.renderAll()
		this.updateLayers()
		this.stateManager.recordState()
		return true;
	}
	/** 设置激活对象可擦除 */
	setActiveObjectErasable() {
		const objects = this.canvasManager.getObjects()
		objects.forEach((item: any) => {
			item.set({
				erasable: (item?.info?.id === this.activeID.value && item.type !== "group")
			})
		})
	}
	/** 设置所有对象擦除属性 */
	setAllObjectsErasable(isErasable = false) {
		const objects = this.canvasManager.getObjects()
		objects.forEach((item: any) => {
			item.set({ erasable: isErasable })
		})
	}

	/** 更新图层缩略图 */
	async updateLayerThumbnailsById(id: string, thumbnail?: string, isUpdate = true) {
		const object = this.canvasManager.getObjectById(id);
		if (!object) return;
		const url = thumbnail || await exportObjectToThumbnail(object);
		object.thumbnail = url
		if (isUpdate) this.updateLayers()
	}

	dispose() { }
}