import { fabric } from "fabric-with-all";
import { OperationType } from "../tools/layerHelper";

/**
 * 笔刷指示器
 * 在画笔模式下显示当前笔刷大小的圆圈指示器
 * 使用独立的 fabric.StaticCanvas，完全不干扰主画布的绘制流程
 */
export class BrushIndicator {
	/**
	 * 构造函数
	 * @param {Object} canvas fabric.js画布实例
	 * @param {Object} options 配置选项
	 */
	constructor(canvas, options = {}) {
		this.canvas = canvas;
		this.options = {
			strokeColor: options.strokeColor || "rgba(0, 0, 0, 0.5)",
			strokeWidth: options.strokeWidth || 1,
			fillColor: options.fillColor || "rgba(0, 0, 0, 0.1)",
			...options,
		};

		// 创建独立的静态画布
		this.indicatorCanvas = null;
		this.staticCanvas = null;
		this.indicatorCircle = null;

		// 事件处理器
		this._mouseEnterHandler = null;
		this._mouseLeaveHandler = null;
		this._mouseMoveHandler = null;
		this._zoomHandler = null;
		this._viewportHandler = null;

		// 当前状态
		this.isVisible = false;
		this.currentSize = 10;
		this.isEnabled = false;
		this.currentPosition = { x: 0, y: 0 };

		// 缓存画布状态，用于优化性能
		this._lastCanvasState = {
			width: null,
			height: null,
			zoom: null,
			viewportTransform: null,
		};
		this._createStaticCanvas();
	}

	/**
	 * 创建独立的 fabric.StaticCanvas 画布层
	 * @private
	 */
	_createStaticCanvas() {
		if (!this.canvas.wrapperEl) return;

		// 创建独立的 canvas 元素
		this.indicatorCanvas = document.createElement("canvas");
		this.indicatorCanvas.className = "brush-indicator-canvas";

		// 设置样式，使其覆盖在主画布上
		Object.assign(this.indicatorCanvas.style, {
			position: "absolute",
			top: "0",
			left: "0",
			pointerEvents: "none", // 不阻挡鼠标事件
			zIndex: "10", // 确保在最上层
			width: "100%",
			height: "100%",
		});

		// 将指示器画布添加到 fabric.js 画布容器中
		this.canvas.wrapperEl.appendChild(this.indicatorCanvas);

		// 创建 fabric.StaticCanvas 实例
		this.staticCanvas = new fabric.StaticCanvas(this.indicatorCanvas, {
			enableRetinaScaling: this.canvas.enableRetinaScaling,
			allowTouchScrolling: false,
			selection: false,
			skipTargetFind: true,
			preserveObjectStacking: true,
		});

		// 同步画布尺寸和变换
		this._syncCanvasProperties();

		// 监听主画布变化
		this._observeCanvasChanges();
	}

	/**
	 * 同步画布属性（尺寸、缩放、视口变换等）
	 * @private
	 */
	_syncCanvasProperties() {
		if (!this.staticCanvas || !this.canvas) return;

		// 检查是否为笔刷或橡皮擦模式，非相关模式直接返回
		const isBrushMode =
			this.canvas.isDrawingMode && this.canvas.freeDrawingBrush;
		const isEraserMode =
			this.canvas.isDrawingMode &&
			this.canvas.freeDrawingBrush &&
			this.canvas.freeDrawingBrush.type === "eraser";

		const isLiquifyMode = this.canvas.toolId === OperationType.LIQUIFY;// 检查是否在液化模式
		if ([isBrushMode, isEraserMode, isLiquifyMode].every(v => !v)) return;

		let hasChanges = false;

		// 检查画布尺寸是否变化
		const currentWidth = this.canvas.width;
		const currentHeight = this.canvas.height;
		if (
			currentWidth !== this._lastCanvasState.width ||
			currentHeight !== this._lastCanvasState.height
		) {
			this.staticCanvas.setWidth(currentWidth);
			this.staticCanvas.setHeight(currentHeight);
			this._lastCanvasState.width = currentWidth;
			this._lastCanvasState.height = currentHeight;
			hasChanges = true;
		}

		// 检查缩放比例是否变化
		const currentZoom = this.canvas.getZoom();
		if (Math.abs(currentZoom - (this._lastCanvasState.zoom || 0)) > 0.001) {
			this.staticCanvas.setZoom(currentZoom);
			this._lastCanvasState.zoom = currentZoom;
			hasChanges = true;
		}

		// 检查视口变换是否变化
		const currentVpt = this.canvas.viewportTransform;
		if (
			currentVpt &&
			!this._areViewportTransformsEqual(
				currentVpt,
				this._lastCanvasState.viewportTransform
			)
		) {
			this.staticCanvas.setViewportTransform([...currentVpt]);
			this._lastCanvasState.viewportTransform = [...currentVpt];
			hasChanges = true;
		}

		// 只有在有变化时才重新渲染
		if (hasChanges) {
			this.staticCanvas.renderAll();
		}
	}

	/**
	 * 比较两个视口变换矩阵是否相等
	 * @private
	 * @param {Array} vpt1 视口变换矩阵1
	 * @param {Array} vpt2 视口变换矩阵2
	 * @returns {Boolean} 是否相等
	 */
	_areViewportTransformsEqual(vpt1, vpt2) {
		if (!vpt1 || !vpt2) return false;
		if (vpt1.length !== vpt2.length) return false;

		const tolerance = 0.001;
		for (let i = 0; i < vpt1.length; i++) {
			if (Math.abs(vpt1[i] - vpt2[i]) > tolerance) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 监听主画布变化
	 * @private
	 */
	_observeCanvasChanges() {
		if (!this.canvas) return;

		// 监听缩放变化
		this._zoomHandler = () => {
			this._syncCanvasProperties();
		};

		// 监听视口变化
		this._viewportHandler = () => {
			this._syncCanvasProperties();
		};

		// 监听画布尺寸变化
		this._resizeHandler = () => {
			this._syncCanvasProperties();
		};

		// 绑定事件
		this.canvas.on("after:render", this._zoomHandler);
		this.canvas.on("canvas:zoomed", this._zoomHandler);
		this.canvas.on("viewport:changed", this._viewportHandler);
		this.canvas.on("canvas:resized", this._resizeHandler);

		// 使用 ResizeObserver 监听 DOM 尺寸变化
		if (window.ResizeObserver && this.canvas.upperCanvasEl) {
			this.resizeObserver = new ResizeObserver(() => {
				this._syncCanvasProperties();
			});
			this.resizeObserver.observe(this.canvas.upperCanvasEl);
		}
	}

	/**
	 * 启用笔刷指示器
	 * @param {Number} brushSize 笔刷大小
	 */
	enable(brushSize) {
		if (this.isEnabled) return;

		this.isEnabled = true;
		this.currentSize = brushSize;

		// 绑定事件
		this._bindEvents();
	}

	/**
	 * 禁用笔刷指示器
	 */
	disable() {
		if (!this.isEnabled) return;

		this.isEnabled = false;

		// 隐藏指示器
		this.hide();

		// 重置颜色配置为默认值
		this.options.strokeColor = "";
		this.options.fillColor = "";

		// 解绑事件
		this._unbindEvents();
	}

	/**
	 * 更新笔刷大小
	 * @param {Number} size 新的笔刷大小
	 */
	updateSize(size) {
		this.currentSize = size;

		// 如果指示器正在显示，更新其大小
		if (this.isVisible && this.indicatorCircle) {
			this.indicatorCircle.set({
				radius: size / 2,
			});
			this.staticCanvas.renderAll();
		}
	}

	/**
	 * 更新指示器颜色
	 * @param {String} color 新的颜色值
	 */
	updateColor(color) {
		// 更新配置选项中的颜色
		if (color) {
			this.options.strokeColor = color;
		}

		// 如果指示器正在显示，更新其颜色
		if (this.isVisible && this.indicatorCircle) {
			this.indicatorCircle.set({
				stroke: this.options.strokeColor,
				fill: this.options.fillColor,
			});
			this.staticCanvas.renderAll();
		}
	}

	/**
	 * 显示指示器
	 * @param {Object} pointer 鼠标位置
	 */
	show(pointer) {
		if (!this.isEnabled || this.isVisible) return;

		this.isVisible = true;

		// 创建指示器圆圈
		this._createIndicatorCircle();

		// 更新位置
		this.updatePosition(pointer);
	}

	/**
	 * 隐藏指示器
	 */
	hide() {
		if (!this.isVisible) return;

		this.isVisible = false;

		// 移除指示器圆圈
		if (this.indicatorCircle && this.staticCanvas) {
			this.staticCanvas.remove(this.indicatorCircle);
			this.indicatorCircle = null;
			this.staticCanvas.renderAll();
		}
	}

	/**
	 * 更新指示器位置
	 * @param {Object} pointer 鼠标位置
	 */
	updatePosition(pointer) {
		if (!this.isVisible || !this.indicatorCircle) return;

		let canvasPointer;
		// 如果是原生事件（如 e.e），优先用 clientX/clientY 转换
		if (
			pointer &&
			pointer.clientX !== undefined &&
			pointer.clientY !== undefined
		) {
			// 获取主画布的包裹元素位置
			const rect = this.canvas.upperCanvasEl.getBoundingClientRect();
			const x = pointer.clientX - rect.left;
			const y = pointer.clientY - rect.top;
			// 逆变换到画布坐标
			canvasPointer = fabric.util.transformPoint(
				new fabric.Point(x, y),
				fabric.util.invertTransform(this.canvas.viewportTransform)
			);
		} else {
			// 兼容 fabric 的 getPointer
			canvasPointer = this.canvas.getPointer(pointer);
		}

		// 更新当前位置
		this.currentPosition = {
			x: canvasPointer.x,
			y: canvasPointer.y,
		};

		// 更新指示器位置
		this.indicatorCircle.set({
			left: canvasPointer.x,
			top: canvasPointer.y,
		});

		// 优化渲染
		this.staticCanvas.requestRenderAll();
	}

	/**
	 * 创建指示器圆圈对象
	 * @private
	 */
	_createIndicatorCircle() {
		if (this.indicatorCircle || !this.staticCanvas) return;

		// 创建圆圈对象
		this.indicatorCircle = new fabric.Circle({
			radius: this.currentSize / 2,
			fill: this.options.fillColor,
			stroke: this.options.strokeColor,
			strokeWidth: this.options.strokeWidth,
			originX: "center",
			originY: "center",
			selectable: false,
			evented: false,
			excludeFromExport: true,
			isTemp: true,
			pointer: true,
		});

		// 添加到静态画布
		this.staticCanvas.add(this.indicatorCircle);
	}

	/**
	 * 绑定事件处理器
	 * @private
	 */
	_bindEvents() {
		if (!this.canvas) return;

		// 鼠标进入画布
		this._mouseEnterHandler = (e) => {
			if (this._shouldShowIndicator()) {
				this.show(e.e);
				const currentVpt = this.canvas.viewportTransform;
				this.staticCanvas.setViewportTransform([...currentVpt]);
				this.staticCanvas.renderAll();
			}
		};

		// 鼠标离开画布
		this._mouseLeaveHandler = () => {
			this.hide();
		};

		// 鼠标移动
		this._mouseMoveHandler = (e) => {
			if (this._shouldShowIndicator()) {
				if (!this.isVisible) {
					//   this.show(e.e);
					this._mouseEnterHandler && this._mouseEnterHandler(e)
				} else {
					// requestIdleCallback(() => {
					//   this.updatePosition(e.e);
					// });

					requestAnimationFrame(() => {
						this.updatePosition(e.e);
					});
				}
			} else {
				this.hide();
			}
		};

		// 绑定事件
		this.canvas.on("mouse:over", this._mouseEnterHandler);
		this.canvas.on("mouse:out", this._mouseLeaveHandler);
		this.canvas.on("mouse:move", this._mouseMoveHandler);
		
		this._observeCanvasChanges();
	}

	/**
	 * 解绑事件处理器
	 * @private
	 */
	_unbindEvents() {
		if (!this.canvas) return;
		// 解绑鼠标事件
		if (this._mouseEnterHandler) {
			this.canvas.off("mouse:over", this._mouseEnterHandler);
			this._mouseEnterHandler = null;
		}

		if (this._mouseLeaveHandler) {
			this.canvas.off("mouse:out", this._mouseLeaveHandler);
			this._mouseLeaveHandler = null;
		}

		if (this._mouseMoveHandler) {
			this.canvas.off("mouse:move", this._mouseMoveHandler);
			this._mouseMoveHandler = null;
		}

		// 解绑画布变化事件
		if (this._zoomHandler) {
			this.canvas.off("after:render", this._zoomHandler);
			this.canvas.off("canvas:zoomed", this._zoomHandler);
			this._zoomHandler = null;
		}

		if (this._viewportHandler) {
			this.canvas.off("viewport:changed", this._viewportHandler);
			this._viewportHandler = null;
		}

		if (this._resizeHandler) {
			this.canvas.off("canvas:resized", this._resizeHandler);
			this._resizeHandler = null;
		}
	}

	/**
	 * 判断是否应该显示指示器
	 * @private
	 * @returns {Boolean} 是否显示
	 */
	_shouldShowIndicator() {
		const isDrawingMode = this.canvas.isDrawingMode;// 检查画布是否在绘图模式
		const isLiquifyMode = this.canvas.toolId === OperationType.LIQUIFY;// 检查是否在液化模式
		// console.log(`笔刷指示器\n绘图模式:${isDrawingMode}\n液化模式:${isLiquifyMode}`)
		// 检查画布是否在绘图模式OR液化模式
		if ([isDrawingMode, isLiquifyMode].every(v => !v)) return false;

		// 检查是否有笔刷
		if (!this.canvas.freeDrawingBrush) return false;

		return true;
	}

	/**
	 * 销毁指示器
	 */
	dispose() {
		this.disable();

		// 解绑画布变化事件
		this._unbindEvents();

		// 停止监听尺寸变化
		if (this.resizeObserver) {
			this.resizeObserver.disconnect();
			this.resizeObserver = null;
		}

		// 销毁静态画布
		if (this.staticCanvas) {
			this.staticCanvas.dispose();
			this.staticCanvas = null;
		}

		// 移除指示器画布
		if (this.indicatorCanvas && this.indicatorCanvas.parentNode) {
			this.indicatorCanvas.parentNode.removeChild(this.indicatorCanvas);
		}

		this.canvas = null;
		this.indicatorCanvas = null;
		this.indicatorCircle = null;
		this.options = null;
	}
}
