export function deepCompare(obj1, obj2) {
  const diff = {};

  // 处理基础类型
  if (obj1 === obj2) {
    return null;
  }

  if (obj1 === null || obj2 === null || typeof obj1 !== "object" || typeof obj2 !== "object") {
    return { _value: obj2, _oldValue: obj1 };
  }

  // 处理数组
  if (Array.isArray(obj1) && Array.isArray(obj2)) {
    if (obj1.length !== obj2.length) {
      return { _value: obj2, _oldValue: obj1 };
    }

    for (let i = 0; i < obj1.length; i++) {
      const itemDiff = deepCompare(obj1[i], obj2[i]);
      if (itemDiff !== null) {
        diff[i] = itemDiff;
      }
    }

    return Object.keys(diff).length > 0 ? diff : null;
  }

  // 处理对象
  const allKeys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);

  for (const key of allKeys) {
    const val1 = obj1[key];
    const val2 = obj2[key];

    if (!(key in obj1)) {
      diff[key] = { _value: val2, _type: "added" };
    } else if (!(key in obj2)) {
      diff[key] = { _value: undefined, _oldValue: val1, _type: "removed" };
    } else {
      const itemDiff = deepCompare(val1, val2);
      if (itemDiff !== null) {
        diff[key] = itemDiff;
      }
    }
  }

  return Object.keys(diff).length > 0 ? diff : null;
}

/**
 * 深度克隆对象
 * @param {any} obj 要克隆的对象
 * @returns {any} 克隆后的对象
 */
export function deepClone(obj) {
  if (obj === null || typeof obj !== "object") {
    return obj;
  }

  if (obj instanceof Date) {
    return new Date(obj);
  }

  if (obj instanceof RegExp) {
    return new RegExp(obj);
  }

  if (Array.isArray(obj)) {
    return obj.map((item) => deepClone(item));
  }

  if (typeof obj === "object") {
    const cloned = {};
    for (const key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        cloned[key] = deepClone(obj[key]);
      }
    }
    return cloned;
  }

  return obj;
}

/**
 * 应用差异到基础对象
 * @param {Object} baseObj 基础对象
 * @param {Object} diff 差异对象
 * @returns {Object} 应用差异后的对象
 */
export function applyDiff(baseObj, diff) {
  if (!diff) {
    return deepClone(baseObj);
  }

  // 如果是直接值替换
  if (diff._value !== undefined) {
    return diff._value;
  }

  const result = deepClone(baseObj) || {};

  for (const key in diff) {
    const change = diff[key];

    if (change._type === "added" || change._type === "removed") {
      if (change._type === "removed") {
        delete result[key];
      } else {
        result[key] = change._value;
      }
    } else if (change._value !== undefined) {
      result[key] = change._value;
    } else {
      // 递归应用嵌套差异
      result[key] = applyDiff(result[key], change);
    }
  }

  return result;
}

/**
 * 节流函数
 * @param {Function} func 要节流的函数
 * @param {number} wait 等待时间
 * @returns {Function} 节流后的函数
 */
export function throttle(func, wait) {
  let timeout;
  let previous = 0;

  return function executedFunction(...args) {
    const now = Date.now();
    const remaining = wait - (now - previous);

    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      previous = now;
      return func.apply(this, args);
    } else if (!timeout) {
      timeout = setTimeout(() => {
        previous = Date.now();
        timeout = null;
        func.apply(this, args);
      }, remaining);
    }
  };
}

/**
 * 防抖函数
 * @param {Function} func 要防抖的函数
 * @param {number} wait 等待时间
 * @param {boolean} immediate 是否立即执行
 * @returns {Function} 防抖后的函数
 */
export function debounce(func, wait, immediate = false) {
  let timeout;

  return function executedFunction(...args) {
    const later = () => {
      timeout = null;
      if (!immediate) func.apply(this, args);
    };

    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);

    if (callNow) func.apply(this, args);
  };
}

/**
 * 生成唯一ID
 * @param {string} prefix 前缀
 * @returns {string} 唯一ID
 */
export function generateId(prefix = "id") {
  return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}

/**
 * 格式化文件大小
 * @param {number} bytes 字节数
 * @returns {string} 格式化后的大小
 */
export function formatFileSize(bytes) {
  if (bytes === 0) return "0 Bytes";

  const k = 1024;
  const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
}

/**
 * 格式化时间差
 * @param {number} milliseconds 毫秒数
 * @returns {string} 格式化后的时间
 */
export function formatDuration(milliseconds) {
  if (milliseconds < 1000) {
    return `${milliseconds.toFixed(2)}ms`;
  } else if (milliseconds < 60000) {
    return `${(milliseconds / 1000).toFixed(2)}s`;
  } else {
    const minutes = Math.floor(milliseconds / 60000);
    const seconds = ((milliseconds % 60000) / 1000).toFixed(2);
    return `${minutes}m ${seconds}s`;
  }
}

/**
 * 检查是否是有效的命令对象
 * @param {*} command 命令对象
 * @returns {boolean} 是否有效
 */
export function isValidCommand(command) {
  return command && typeof command === "object" && typeof command.execute === "function";
}

/**
 * 检查是否是Promise
 * @param {*} obj 对象
 * @returns {boolean} 是否是Promise
 */
export function isPromise(obj) {
  return obj && typeof obj.then === "function";
}

/**
 * 安全的JSON解析
 * @param {string} jsonString JSON字符串
 * @param {*} defaultValue 默认值
 * @returns {*} 解析结果
 */
export function safeJSONParse(jsonString, defaultValue = null) {
  try {
    return JSON.parse(jsonString);
  } catch (error) {
    console.warn("JSON解析失败:", error);
    return defaultValue;
  }
}

/**
 * 安全的JSON序列化
 * @param {*} obj 要序列化的对象
 * @param {*} defaultValue 默认值
 * @returns {string} JSON字符串
 */
export function safeJSONStringify(obj, defaultValue = "{}") {
  try {
    return JSON.stringify(obj);
  } catch (error) {
    console.warn("JSON序列化失败:", error);
    return defaultValue;
  }
}

/**
 * 计算对象深度
 * @param {*} obj 对象
 * @returns {number} 深度
 */
export function getObjectDepth(obj) {
  if (obj === null || typeof obj !== "object") {
    return 0;
  }

  let maxDepth = 0;
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      const depth = getObjectDepth(obj[key]);
      maxDepth = Math.max(maxDepth, depth);
    }
  }

  return maxDepth + 1;
}

/**
 * 计算对象大小（字节）
 * @param {*} obj 对象
 * @returns {number} 大小（字节）
 */
export function getObjectSize(obj) {
  const jsonString = safeJSONStringify(obj, "{}");
  return new Blob([jsonString]).size;
}

/**
 * 检查浏览器支持
 * @returns {Object} 支持信息
 */
export function checkBrowserSupport() {
  return {
    WeakRef: typeof WeakRef !== "undefined",
    FinalizationRegistry: typeof FinalizationRegistry !== "undefined",
    PerformanceMemory: typeof performance !== "undefined" && !!performance.memory,
    RequestIdleCallback: typeof requestIdleCallback !== "undefined",
    IntersectionObserver: typeof IntersectionObserver !== "undefined",
    ResizeObserver: typeof ResizeObserver !== "undefined",
  };
}

/**
 * 延迟执行
 * @param {number} ms 延迟毫秒数
 * @returns {Promise} Promise对象
 */
export function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

/**
 * 重试执行函数
 * @param {Function} fn 要执行的函数
 * @param {Object} options 重试选项
 * @returns {Promise} 执行结果
 */
export async function retry(fn, options = {}) {
  const { retries = 3, delay: delayMs = 1000, backoff = 1.5, shouldRetry = () => true } = options;

  let attempt = 0;
  let currentDelay = delayMs;

  while (attempt <= retries) {
    try {
      return await fn();
    } catch (error) {
      attempt++;

      if (attempt > retries || !shouldRetry(error)) {
        throw error;
      }

      await delay(currentDelay);
      currentDelay *= backoff;
    }
  }
}

/**
 * 批处理执行
 * @param {Array} items 要处理的项目
 * @param {Function} processor 处理函数
 * @param {Object} options 批处理选项
 * @returns {Promise<Array>} 处理结果
 */
export async function batchProcess(items, processor, options = {}) {
  const { batchSize = 10, delay: delayMs = 0, onProgress = () => {} } = options;

  const results = [];

  for (let i = 0; i < items.length; i += batchSize) {
    const batch = items.slice(i, i + batchSize);
    const batchResults = await Promise.all(batch.map((item) => processor(item)));

    results.push(...batchResults);

    onProgress({
      completed: Math.min(i + batchSize, items.length),
      total: items.length,
      percentage: Math.min(((i + batchSize) / items.length) * 100, 100),
    });

    if (delayMs > 0 && i + batchSize < items.length) {
      await delay(delayMs);
    }
  }

  return results;
}

/**
 * 创建可取消的Promise
 * @param {Function} executor Promise执行器
 * @returns {Object} 包含promise和cancel方法的对象
 */
export function createCancellablePromise(executor) {
  let isCancelled = false;
  let cancelCallback = null;

  const promise = new Promise((resolve, reject) => {
    const wrappedResolve = (value) => {
      if (!isCancelled) resolve(value);
    };

    const wrappedReject = (error) => {
      if (!isCancelled) reject(error);
    };

    cancelCallback = () => {
      isCancelled = true;
      reject(new Error("Promise was cancelled"));
    };

    executor(wrappedResolve, wrappedReject);
  });

  return {
    promise,
    cancel: () => {
      if (cancelCallback) {
        cancelCallback();
      }
    },
    isCancelled: () => isCancelled,
  };
}

/**
 * 增强版检查对象是否在画布中（包括组内对象）
 * @param {fabric.Canvas} canvas 画布实例
 * @param {fabric.Object} targetObj 目标对象
 * @returns {Object} { flag: boolean, object: fabric.Object, parent: fabric.Group|null }
 */
export function objectIsInCanvas(canvas, targetObj) {
  if (!canvas || !targetObj) {
    return { flag: false, object: null, parent: null };
  }

  const targetId = targetObj.id;
  const targetLayerId = targetObj.layerId;
  if (!targetId && !targetLayerId) {
    return { flag: false, object: null, parent: null };
  }

  // 首先检查顶层对象
  const topLevelObjects = canvas.getObjects();

  // 直接在顶层查找
  const directMatch = topLevelObjects.find((obj) => {
	const isId = !targetId ? true : obj.id === targetId;
	const isLayerId = !targetLayerId ? true : obj.layerId === targetLayerId;
	return isId && isLayerId;
  });
  if (directMatch) {
    return { flag: true, object: directMatch, parent: null };
  }

  // 递归检查组内对象
  for (const obj of topLevelObjects) {
    if (obj.type === "group") {
      const result = findObjectInGroup(obj, targetId);
      if (result.found) {
        return { flag: true, object: result.object, parent: obj };
      }
    }
  }

  return { flag: false, object: null, parent: null };
}

/**
 * 在组中递归查找对象
 * @param {fabric.Group} group 组对象
 * @param {string} targetId 目标对象ID
 * @returns {Object} { found: boolean, object: fabric.Object|null }
 */
function findObjectInGroup(group, targetId) {
  if (!group || group.type !== "group" || !group.getObjects) {
    return { found: false, object: null };
  }

  const groupObjects = group.getObjects();

  for (const obj of groupObjects) {
    if (obj.id === targetId) {
      return { found: true, object: obj };
    }

    // 递归检查嵌套组
    if (obj.type === "group") {
      const nestedResult = findObjectInGroup(obj, targetId);
      if (nestedResult.found) {
        return nestedResult;
      }
    }
  }

  return { found: false, object: null };
}

/**
 * 通过ID查找对象（增强版）
 * @param {fabric.Canvas} canvas 画布实例
 * @param {string} objectId 对象ID
 * @returns {Object} { object: fabric.Object|null, parent: fabric.Group|null }
 */
export function findObjectById(canvas, objectId) {
  if (!canvas || !objectId) {
    return { object: null, parent: null };
  }

  const result = objectIsInCanvas(canvas, { id: objectId });
  return { object: result.object, parent: result.parent };
}

/**
 * 通过layerID查找对象（增强版）
 * @param {fabric.Canvas} canvas 画布实例
 * @param {string} layerId 图层ID
 * @returns {Object} { object: fabric.Object|null, parent: fabric.Group|null }
 */
export function findObjectByLayerId(canvas, layerId) {
  if (!canvas || !layerId) {
    return { object: null, parent: null };
  }

  const result = objectIsInCanvas(canvas, { layerId: layerId });
  return { object: result.object, parent: result.parent };
}


/**
 * 安全移除画布对象（包括组内对象）
 * @param {fabric.Canvas} canvas 画布实例
 * @param {fabric.Object} targetObj 目标对象
 * @returns {boolean} 是否成功移除
 */
export function removeCanvasObjectByObject(canvas, targetObj) {
  if (!canvas || !targetObj) {
    return false;
  }

  const result = objectIsInCanvas(canvas, targetObj);

  if (!result.flag) {
    return false;
  }

  try {
    if (result.parent) {
      // 对象在组中，从组中移除
      result.parent.removeWithUpdate(result.object);
    } else {
      // 对象在顶层，直接从画布移除
      canvas.remove(result.object);
    }
    return true;
  } catch (error) {
    console.error("移除对象时发生错误:", error);
    return false;
  }
}

/**
 *  优化画布渲染   统一渲染完成后才执行
 * @param {fabric.Canvas} canvas 画布实例
 * @param {Function} callback 渲染执行函数
 */
export const optimizeCanvasRendering = async (canvas, callback) => {
  return new Promise((resolve) => {
    if (!canvas || typeof callback !== "function") {
      resolve();
      return;
    }

    // 暂停渲染以提高性能
    canvas.skipTargetFind = true;
    // 开始渲染
    // 暂停实时渲染和对象查找
    const wasRenderOnAddRemove = canvas.renderOnAddRemove;
    canvas.renderOnAddRemove = false; // 禁用自动渲染

    // 等待下一帧渲染完成
    requestAnimationFrame(async () => {
      // 恢复渲染设置
      canvas.skipTargetFind = false;
      canvas.renderOnAddRemove = wasRenderOnAddRemove;
      if (isPromise(callback)) {
        await callback?.();
      } else {
        callback?.();
      }
      canvas.renderAll(); // 确保画布重新渲染 - 同步渲染
      resolve();
    });
  });
};

/**
 * 获取对象在画布中的z-index位置
 * @param {fabric.Canvas} canvas 画布实例
 * @param {fabric.Object} targetObj 目标对象
 * @returns {number} z-index位置，-1表示未找到
 */
export function getObjectZIndex(canvas, targetObj) {
  if (!canvas || !targetObj) {
    return -1;
  }

  const result = objectIsInCanvas(canvas, targetObj);
  if (!result.flag) {
    return -1;
  }

  if (result.parent) {
    // 对象在组中，返回组在画布中的位置
    const allObjects = canvas.getObjects();
    return allObjects.indexOf(result.parent);
  } else {
    // 对象在顶层，直接返回在画布中的位置
    const allObjects = canvas.getObjects();
    return allObjects.indexOf(result.object);
  }
}

/**
 * 在指定的z-index位置插入对象
 * @param {fabric.Canvas} canvas 画布实例
 * @param {fabric.Object} object 要插入的对象
 * @param {number} zIndex z-index位置
 * @param {boolean} renderAll 是否立即渲染，默认true
 * @returns {boolean} 是否成功插入
 */
export function insertObjectAtZIndex(canvas, object, zIndex, renderAll = true, isReplace = false) {
  if (!canvas || !object || zIndex < 0) {
    return false;
  }

  try {
    // 确保z-index不超过当前对象数量
    const maxIndex = canvas.getObjects().length;
    const safeZIndex = Math.min(zIndex, maxIndex);

    canvas.insertAt(object, safeZIndex, isReplace);

    if (renderAll) {
      canvas.renderAll();
    }

    return true;
  } catch (error) {
    console.error("插入对象到指定z-index位置失败:", error);
    return false;
  }
}

/**
 * 移动对象到指定的z-index位置
 * @param {fabric.Canvas} canvas 画布实例
 * @param {fabric.Object} object 要移动的对象
 * @param {number} zIndex 目标z-index位置
 * @param {boolean} renderAll 是否立即渲染，默认true
 * @returns {boolean} 是否成功移动
 */
export function moveObjectToZIndex(canvas, object, zIndex, renderAll = true) {
  if (!canvas || !object || zIndex < 0) {
    return false;
  }

  const result = objectIsInCanvas(canvas, object);
  if (!result.flag) {
    console.warn("对象不在画布中，无法移动");
    return false;
  }

  try {
    // 确保z-index不超过当前对象数量-1（因为当前对象也在其中）
    const maxIndex = canvas.getObjects().length - 1;
    const safeZIndex = Math.min(zIndex, maxIndex);

    result.object.moveTo(safeZIndex);

    if (renderAll) {
      canvas.renderAll();
    }

    return true;
  } catch (error) {
    console.error("移动对象到指定z-index位置失败:", error);
    return false;
  }
}

/**
 * 交换两个对象的z-index位置
 * @param {fabric.Canvas} canvas 画布实例
 * @param {fabric.Object} obj1 第一个对象
 * @param {fabric.Object} obj2 第二个对象
 * @param {boolean} renderAll 是否立即渲染，默认true
 * @returns {boolean} 是否成功交换
 */
export function swapObjectsZIndex(canvas, obj1, obj2, renderAll = true) {
  if (!canvas || !obj1 || !obj2) {
    return false;
  }

  const zIndex1 = getObjectZIndex(canvas, obj1);
  const zIndex2 = getObjectZIndex(canvas, obj2);

  if (zIndex1 === -1 || zIndex2 === -1) {
    console.warn("其中一个或两个对象不在画布中");
    return false;
  }

  try {
    // 先移动z-index较大的对象，避免索引冲突
    if (zIndex1 > zIndex2) {
      moveObjectToZIndex(canvas, obj2, zIndex1, false);
      moveObjectToZIndex(canvas, obj1, zIndex2, false);
    } else {
      moveObjectToZIndex(canvas, obj1, zIndex2, false);
      moveObjectToZIndex(canvas, obj2, zIndex1, false);
    }

    if (renderAll) {
      canvas.renderAll();
    }

    return true;
  } catch (error) {
    console.error("交换对象z-index位置失败:", error);
    return false;
  }
}

/**
 * 获取画布中所有对象的z-index信息
 * @param {fabric.Canvas} canvas 画布实例
 * @returns {Array} 包含对象ID和z-index的数组
 */
export function getAllObjectsZIndex(canvas) {
  if (!canvas) {
    return [];
  }

  const objects = canvas.getObjects();
  return objects.map((obj, index) => ({
    id: obj.id || `unnamed_${index}`,
    zIndex: index,
    type: obj.type,
    layerId: obj.layerId,
    object: obj,
  }));
}

/**
 * 按图层ID获取对象的z-index信息
 * @param {fabric.Canvas} canvas 画布实例
 * @param {string} layerId 图层ID
 * @returns {Array} 属于指定图层的对象z-index信息
 */
export function getLayerObjectsZIndex(canvas, layerId) {
  if (!canvas || !layerId) {
    return [];
  }

  const allInfo = getAllObjectsZIndex(canvas);
  return allInfo.filter((info) => info.layerId === layerId);
}


/**
 * 计算两点之间的角度
 * @param {number} x1 第一个点的x坐标
 * @param {number} y1 第一个点的y坐标
 * @param {number} x2 第二个点的x坐标
 * @param {number} y2 第二个点的y坐标
 * @returns {number} 角度值（-180 - 180度）
*/
export function calculateAngle(x1, y1, x2, y2, int = false) {
    const deltaX = x2 - x1;
    const deltaY = y1 - y2;
    let angle = Math.atan2(deltaX, deltaY) * (180 / Math.PI);
	// if(angle < 0) angle += 360;// 0 - 360度
    return int ? Math.round(angle) : angle;
}

/**
 * 通过角度计算直线上的两点坐标返回0-1范围的坐标
 * @param {number} angle 角度值（0-360度）
 * @returns {{x1: number, y1: number, x2: number, y2: number}} 包含两个点坐标
*/
export function calculateLinePoints(angle) {
    // 将角度转换为弧度
    const radian = (angle - 90) * Math.PI / 180;
    
    // 计算直线上的两点坐标
    const x1 = 0.5 - 0.5 * Math.cos(radian);
    const y1 = 0.5 - 0.5 * Math.sin(radian);
    const x2 = 0.5 + 0.5 * Math.cos(radian);
    const y2 = 0.5 + 0.5 * Math.sin(radian);
    
    return {x1, y1, x2, y2};
}

export function rgbaToHex(rgba){
    const r = rgba.r.toString(16).padStart(2, "0");
    const g = rgba.g.toString(16).padStart(2, "0");
    const b = rgba.b.toString(16).padStart(2, "0");
    return `#${r}${g}${b}`;
}

export function fillToPallet(fill) {
    if(!fill.coords || !fill.colorStops) return {};
	const angle = calculateAngle(fill.coords.x1, fill.coords.y1, fill.coords.x2, fill.coords.y2);
	const colors = new Set();
	// console.log("==========fill", fill);
	const gradientList = fill.colorStops.map((stop) => {
		colors.add(stop.color);
		const rgbas = stop.color.replace("rgb(", "").replace("rgba(", "").replace(")", "").split(", ");
		const rgba = {
			r: parseInt(rgbas[0]),
			g: parseInt(rgbas[1]),
			b: parseInt(rgbas[2]),
			a: parseFloat(rgbas[3]),
		};
		if(isNaN(rgba.r)) rgba.r = 0;
		if(isNaN(rgba.g)) rgba.g = 0;
		if(isNaN(rgba.b)) rgba.b = 0;
		if(isNaN(rgba.a)) rgba.a = 1;
		return {
			rgba: rgba,
			left: parseInt(stop.offset * 100) + "%",
		};
	});
	const isGradient = colors.size > 1;
	if(isGradient) {
		return {
			// hex: rgbaToHex(gradientList[0].rgba),
			rgba: gradientList[0].rgba,
			gradient:{ angle, selectIndex: 0, gradientShow: true, gradientList },
		};
	} else {
		return {
			hex: rgbaToHex(gradientList[0].rgba),
			rgba: gradientList[0].rgba,
		};
	}
}

export function  palletToFill(pallet) {
	const fill = {
		coords: calculateLinePoints(0),
		colorStops: [
			{ offset: 0, color: "rgba(0, 0, 0, 0)" },
			{ offset: 1, color: "rgba(0, 0, 0, 0)" }
		]
	}
	if(pallet?.gradient){
		let obj = pallet.gradient;
		fill.coords = calculateLinePoints(obj.angle);
		if(obj.gradientList.length >= 2){
			fill.colorStops = obj.gradientList.map(item => ({
				offset: parseInt(item.left) / 100,
				color: `rgba(${item.rgba.r}, ${item.rgba.g}, ${item.rgba.b}, ${item.rgba.a})`,
			}));
		}
	}else if(pallet?.rgba?.hasOwnProperty("r") && pallet?.rgba?.hasOwnProperty("g") && pallet?.rgba?.hasOwnProperty("b")){
		let rgba = pallet.rgba;
		fill.colorStops = [
			{ offset: 0, color: `rgb(${rgba.r}, ${rgba.g}, ${rgba.b})` },
			{ offset: 1, color: `rgb(${rgba.r}, ${rgba.g}, ${rgba.b})` }
		]
	}
	return fill;
}

export function fillToCssStyle(fill) {
    if(!fill.coords || !fill.colorStops) return "";
	const angle = calculateAngle(fill.coords.x1, fill.coords.y1, fill.coords.x2, fill.coords.y2);
	if(fill.colorStops.every(v => v.color === fill.colorStops[0].color)){
		return fill.colorStops[0].color;
	}else{
		var str = "linear-gradient(" + angle + "deg, ";
		fill.colorStops.forEach((v) => {
			str += `${v.color} ${v.offset * 100}%, `
		})
		return str.slice(0, -2) + ")";
	}
}

/**
 * 根据左上角坐标计算旋转后的新坐标
 * @param {number} W - 宽度
 * @param {number} H - 高度
 * @param {number} currentX - 当前左上角x坐标
 * @param {number} currentY - 当前左上角y坐标
 * @param {number} currentAngleDeg - 当前角度(度)
 * @param {number} newAngleDeg - 新角度(度)
 * @returns {Object} 旋转后的左上角坐标 {x, y}
 */
export function calculateRotatedTopLeftDeg(
	W,
	H,
	currentX,
	currentY,
	currentAngleDeg,
	newAngleDeg
) {
	const currentAngle = (currentAngleDeg * Math.PI) / 180;
	const newAngle = (newAngleDeg * Math.PI) / 180;
	// 1. 用当前角度计算中心点位置
	const cosCurrent = Math.cos(currentAngle);
	const sinCurrent = Math.sin(currentAngle);
	const Cx = currentX + (W / 2) * cosCurrent - (H / 2) * sinCurrent;
	const Cy = currentY + (W / 2) * sinCurrent + (H / 2) * cosCurrent;

	// 2. 用新角度计算旋转后的左上角位置
	const cosNew = Math.cos(newAngle);
	const sinNew = Math.sin(newAngle);
	const newX = Cx + (-W / 2) * cosNew - (-H / 2) * sinNew;
	const newY = Cy + (-W / 2) * sinNew + (-H / 2) * cosNew;

	return { x: newX, y: newY };
}

/**
 * 根据左上角坐标计算中心点坐标
 * @param {number} W - 宽度
 * @param {number} H - 高度
 * @param {number} currentX - 当前左上角x坐标
 * @param {number} currentY - 当前左上角y坐标
 * @param {number} currentAngleDeg - 当前角度(度)
 * @returns {Object} 中心点坐标 {x, y}
 */
export function calculateCenterPoint(W, H, currentX, currentY, currentAngleDeg) {
	const currentAngle = (currentAngleDeg * Math.PI) / 180;
	const cosCurrent = Math.cos(currentAngle);
	const sinCurrent = Math.sin(currentAngle);
	const Cx = currentX + (W / 2) * cosCurrent - (H / 2) * sinCurrent;
	const Cy = currentY + (W / 2) * sinCurrent + (H / 2) * cosCurrent;
	return { x: Cx, y: Cy };
}



/**
 * 创建缩放+旋转的变换矩阵
 * @param {number} scale - 缩放比例
 * @param {number} angle - 旋转角度（度）
 * @returns {Array} 变换矩阵 [a, b, c, d, e, f]
*/
export function createPatternTransform(scale, angle) {
	// return fabric.util.composeMatrix({
	// 	scaleX: scale,
	// 	scaleY: scale,
	// 	angle: angle,
	// });
	const angle_ = angle * Math.PI / 180;
	const cos = Math.cos(angle_);
	const sin = Math.sin(angle_);

	// 先缩放，后旋转
	return [
		scale * cos,    // a
		scale * sin,    // b
		-scale * sin,   // c
		scale * cos,    // d
		0,              // e (水平位移)
		0               // f (垂直位移)
	];
}
/**
 * 获取变换矩阵的缩放、旋转
 * @param {Array} Transform - 变换矩阵、
 * @returns {Object} 缩放、旋转角度 {scale, angle}
*/
export function getTransformScaleAngle(Transform) {
	const a = Transform[0];
	const b = Transform[1];
	const c = Transform[2];
	const d = Transform[3];
	const scale = Math.sqrt(a * a + b * b);
	const angle = Math.round(Math.atan2(b, a) * 180 / Math.PI);
	return { scale, angle };
}

/**
 * 图片转换为canvas
 * @param {String} base64 - 图片base64编码
 * @param {Number} scale - 缩放比例
 * @param {Boolean} sr - 缩放反转，默认false
 * @returns {Promise<HTMLCanvasElement>} canvas元素
*/
export async function base64ToCanvas(base64, scale = 1, sr = false) {
	return new Promise((resolve, reject) => {
		const image = new Image();
		image.src = base64;
		image.crossOrigin = 'anonymous';
		image.onload = () => {
			image.width = image.width;
			image.height = image.height;
			const canvas = document.createElement('canvas');
			const width = (sr ? image.width / scale : image.width * scale);
			const height = sr ? image.height / scale : image.height * scale;
			canvas.width = width;
			canvas.height = height;
			const ctx = canvas.getContext('2d');
			ctx.clearRect(0, 0, width, height);
			ctx.drawImage(image, 0, 0, width, height);
			resolve(canvas);
		};
		image.onerror = reject;
	});
}
