import { fabric } from 'fabric-with-all'
import { createId } from '../../tools/tools'

/** 智能框选工具管理器 */
export class AISelectboxToolManager {
	// 管理器	
	canvasManager: any
	stateManager: any
	layerManager: any

	isDragging: boolean = false
	startX: number = 0
	startY: number = 0
	demoObject: any
	constructor(options) {
		this.canvasManager = options.canvasManager
		this.stateManager = options.stateManager
		this.layerManager = options.layerManager

	}
	mouseDownEvent(e) {
		this.isDragging = true
		this.startX = e.absolutePointer.x
		this.startY = e.absolutePointer.y
		const rect = new fabric.Rect({
			left: this.startX,
			top: this.startY,
			width: 0,
			height: 0,
			fill: 'transparent',
			stroke: '#000',
			strokeWidth: 1,
			evented: false,
		})
		this.demoObject = rect
		this.canvasManager.canvas.add(rect)
		this.canvasManager.canvas.renderAll()
	}
	mouseMoveEvent(e) {
		if (!this.isDragging) return;
		var width = e.absolutePointer.x - this.startX
		var height = e.absolutePointer.y - this.startY
		var left = this.startX
		var top = this.startY
		if (width < 0) {
			left += width
			width = -width
		}
		if (height < 0) {
			top += height
			height = -height
		}
		this.demoObject.set({ width, height, left, top })
		this.canvasManager.canvas.renderAll()
	}
	mouseUpEvent(e) {
		if (!this.isDragging) return;
		this.isDragging = false;
		const object = this.demoObject.toJSON("evented")
		if (object.width === 0) object.width = 100
		if (object.height === 0) object.height = 100
		// console.log(object)
		this.canvasManager.canvas.remove(this.demoObject)
		this.canvasManager.canvas.renderAll()

		this.createSelectbox()
	}




	loadImageToObject(url) {
		return new Promise((resolve, reject) => {
			fabric.Image.fromURL(url, (img) => {
				resolve(img);
			}, { crossOrigin: "anonymous" });// 防止污染
		});
	}
	rgba = { r: 0, g: 255, b: 0, a: 200 };
	selectionStyle = {
		stroke: "rgba(255, 77, 71, 1)",
		strokeWidth: 1.5,
		strokeDashArray: [4, 4],
		fill: "rgba(255, 186, 186, 0.5)",
		strokeUniform: true, // 保持描边宽度不随缩放改变
		// strokeLineCap: "round",// 折线端点样式
		// strokeLineJoin: "bevel", // 折线连接样式
		// selectable: false,
		// evented: false,
		excludeFromExport: true,
		hoverCursor: "default",
		moveCursor: "default",
	};
	async createSelectbox() {
		const url = "http://118.31.39.42:3000/falls/1a48ed3a-1faa-4fcd-bf07-765dba1702c5.png"
		const image = await this.loadImageToObject(url)
		const canvas = getObjectAlphaToCanvas(image, null, 0, this.rgba);
		const fobject = this.canvasManager.canvas.clipPath
		// const top = fobject.top - fobject.height * scaleY / 2;
		// const left = fobject.left - fobject.width * scaleX / 2;
		const scaleY = fobject.scaleY
		const scaleX = fobject.scaleX
		const top = fobject.top
		const left = fobject.left
		const arr = traceImageContour(canvas);
		let minX = fobject.width;
		let minY = fobject.height;
		const str = arr.map((v) => {
			if (v.x < minX) minX = v.x;
			if (v.y < minY) minY = v.y;
			return `${v.x} ${v.y}`
		}).join(" L ");
		const path = new fabric.Path(`M ${str} z`);
		path.set({
			left: left + minX * scaleX,
			top: top + minY * scaleY,
			scaleX: scaleX,
			scaleY: scaleY,
			...this.selectionStyle,
		});
		const rect1 = new fabric.Rect({
			left: 0,
			top: 0,
			width: 100,
			height: 100,
			fill: '#f00',
			info: {
				id: createId("rect"),
				name: '矩形图层',
			}
		})
		const rect2 = new fabric.Rect({
			left: 200,
			top: 200,
			width: 100,
			height: 100,
			fill: '#ff0',
			info: {
				id: createId("rect"),
				name: '矩形图层',
			}
		})
		this.layerManager.createGroupLayer({
			child: [rect1, rect2],
		})
		// this.canvasManager.canvas.add(path)
		// this.canvasManager.canvas.renderAll()

	}







	dispose() { }
}


/**
 * 获取对象黑白通道画布
 * @param {fabric.Object} object - 要处理的 fabric 对象
 * @param {ImageData} revData - 相反的ImageData，白通道的相同位置是否为透明，revData为白色为透明，黑色为不透明
 * @param {number} diff - 差值，默认 25
 * @param {Object} rgba - 自定义 rgba 值，默认 { r: 255, g: 255, b: 255, a: 255 }
 * @param {boolean} isMerge - 是否合并，true=合并revData，false=反转revData
 * @returns {HTMLCanvasElement|null} 包含黑白通道的画布，或 null 如果失败
*/
export function getObjectAlphaToCanvas(object, revData, diff = 30, rgba = { r: 255, g: 255, b: 255, a: 255 }, isMerge = false) {
	const image = object.getElement();
	if (image.nodeName !== "IMG" && image.nodeName !== "CANVAS") {
		console.warn("对象不是图片");
		return null;
	}
	const { width, height } = image;
	if (!width || !height) {
		console.warn("对象没有元素");
		return null;
	}
	const canvas = document.createElement("canvas");
	canvas.width = width;
	canvas.height = height;
	const ctx = canvas.getContext("2d");
	ctx.drawImage(image, 0, 0, width, height);
	const data = ctx.getImageData(0, 0, width, height);
	for (let i = 0; i < data.data.length; i += 4) {
		const r = data.data[i + 0];
		const g = data.data[i + 1];
		const b = data.data[i + 2];
		const a = data.data[i + 3];
		const revR = revData?.data[i + 0] || 0;
		const revG = revData?.data[i + 1] || 0;
		const revB = revData?.data[i + 2] || 0;
		const revA = revData?.data[i + 3] || 0;
		let isHave = false;
		if (r || g || b || a) {
			if (revR > diff || revG > diff || revB > diff || revA > diff) {
				isHave = false;
			} else {
				isHave = true;
			}
		}
		if (isMerge && (revR || revG || revB || revA)) isHave = true;
		if (isHave) {
			data.data[i + 0] = rgba.r;
			data.data[i + 1] = rgba.g;
			data.data[i + 2] = rgba.b;
			data.data[i + 3] = rgba.a;
		} else {
			data.data[i + 0] = 0;
			data.data[i + 1] = 0;
			data.data[i + 2] = 0;
			data.data[i + 3] = 0;
		}
	}
	ctx.clearRect(0, 0, width, height);
	ctx.putImageData(data, 0, 0);
	return canvas;
}


/**
 * 图片边界跟踪算法(透明底)
 * @param {HTMLCanvasElement} canvas - canvas元素
 * @param {Number} scale - 缩放比例
 * @returns {Array} 边界点数组 [{x, y}, ...]
*/
export function traceImageContour(canvas) {
	const ctx = canvas.getContext("2d", { willReadFrequently: true });
	const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
	const data = imageData.data;
	const width = canvas.width;
	const height = canvas.height;

	// 查找起始点（第一个不透明像素）
	let startX = -1;
	let startY = -1;

	outer: for (let y = 0; y < height; y++) {
		for (let x = 0; x < width; x++) {
			const index = (y * width + x) * 4;
			if (data[index + 3] > 0) {
				startX = x;
				startY = y;
				break outer;
			}
		}
	}

	if (startX === -1) return []; // 没有不透明像素

	// Moore-Neighbor边界跟踪算法
	const contour = [];
	const visited = new Set();
	const directions = [
		[-1, 0],
		[-1, -1],
		[0, -1],
		[1, -1],
		[1, 0],
		[1, 1],
		[0, 1],
		[-1, 1],
	];

	let currentX = startX;
	let currentY = startY;
	let backtrackDir = 4; // 起始方向：右

	do {
		const pointKey = `${currentX},${currentY}`;
		if (!visited.has(pointKey)) {
			contour.push({ x: currentX, y: currentY });
			visited.add(pointKey);
		}

		// 从右方向开始顺时针查找
		let found = false;
		for (let i = 0; i < 8; i++) {
			const dir = (backtrackDir + i) % 8;
			const dx = directions[dir][0];
			const dy = directions[dir][1];
			const checkX = currentX + dx;
			const checkY = currentY + dy;

			if (
				checkX >= 0 &&
				checkX < width &&
				checkY >= 0 &&
				checkY < height
			) {
				const index = (checkY * width + checkX) * 4;
				if (data[index + 3] > 0) {
					currentX = checkX;
					currentY = checkY;
					backtrackDir = (dir + 5) % 8; // 下一个开始查找的方向
					found = true;
					break;
				}
			}
		}

		if (!found) break;
	} while (
		!(currentX === startX && currentY === startY) &&
		visited.size < width * height
	);

	return contour;
}