import {
  _decorator,
  Animation,
  Button,
  Component,
  EditBox,
  editorExtrasTag,
  find,
  isValid,
  js,
  Label,
  Layout,
  Node,
  ProgressBar,
  Quat,
  Slider,
  sp,
  Sprite,
  SpriteFrame,
  tween,
  UIOpacity,
  UITransform,
  Vec3,
} from "cc";

import { ScrollView } from "cc";
import { Prefab } from "cc";
import { instantiate } from "cc";
import BaseUI from "./BaseUI";

export default class UIUtils {
  static destroyNodeDelay(new_prop: Node, arg1: number) {
    setTimeout(() => {
      if (isValid(new_prop)) {
        new_prop.destroy();
      }
    }, arg1);
  }

  static removeEmptyNode(content: Node) {
    let emptyNode = content.getChildByName("EmptyNode");
    if (emptyNode) {
      emptyNode.destroy();
    }
  }

  static moveToNewParentAndAnim(parent: Node, animNode: Node, cb: Function) {
    UIUtils.moveToNewParent(parent, animNode);
    UIUtils.AnimBezierMoveAndScale(
      animNode,
      new Vec3(0, 0, 0),
      0.2,
      0.8,
      () => {
        cb();
      }
    );
  }

  static hideAnim(node: Node, arg1: () => void) {
    tween(node)
      .to(0.2, { scale: new Vec3(0, 0, 0) })
      .call(() => {
        node.active = false;
        node.setScale(new Vec3(1, 1, 1));
        arg1();
      })
      .start();
  }
  static closeUI(node: Node) {
    if (!isValid(node)) {
      return;
    }
    node.active = false;
    node.parent = null;
    node.destroy();
  }
  public static DeepFindChildByName(parentNode: Node, name: string): Node {
    if (!isValid(parentNode)) {
      return null;
    }

    return UIUtils._findInChildren(parentNode, name);
  }
  // 将一个node节点移动到新的父节点
  static moveToNewParent(parent: Node, child: Node) {
    // 先转换child的世界坐标位置
    let cp = child.getWorldPosition(new Vec3());

    // 更换父节点
    child.setParent(parent, false);

    // 转换世界坐标到新父节点的本地坐标系
    const parentUITrans = parent.getComponent(UITransform);

    // 设置新的本地坐标，使其屏幕位置不变
    const newP = parentUITrans.convertToNodeSpaceAR(cp);

    child.setPosition(newP);
  }

  /**
   * Layout子项目依次播放滑入动画
   * @param layout 布局节点
   * @param options 动画选项
   * @param callback 所有动画完成后的回调
   */
  static AnimateLayoutItems(
    layout: Node,
    options: {
      offsetX?: number;
      offsetY?: number;
      delayInterval?: number;
      duration?: number;
      scale?: number;
      easing?: string;
      staggerDirection?: "forward" | "reverse" | "random";
      onItemComplete?: (index: number, node: Node) => void;
    } = {},
    callback?: () => void
  ): void {
    if (!isValid(layout) || !layout.children || layout.children.length === 0) {
      if (callback) callback();
      return;
    }

    const { onItemComplete } = options;

    const children = [...layout.children];
    let completedCount = 0;
    const totalItems = children.length;

    // 先让所有子元素激活，让布局系统计算最终位置
    children.forEach((child) => {
      if (isValid(child)) {
        child.active = true;
      }
    });

    // 强制更新布局
    const layoutComp = layout.getComponent(Layout);
    if (layoutComp) {
      layoutComp.updateLayout();
    }

    // 等待布局更新完成后再开始动画
    setTimeout(() => {
      this.startSlideInAnimations(
        children,
        options,
        callback,
        completedCount,
        totalItems,
        onItemComplete
      );
    }, 0);
  }

  /**
   * 开始滑入动画
   */
  private static startSlideInAnimations(
    children: Node[],
    options: any,
    callback?: () => void,
    completedCount: number = 0,
    totalItems: number = 0,
    onItemComplete?: (index: number, node: Node) => void
  ): void {
    const {
      offsetX,
      offsetY,
      delayInterval,
      duration = 0.3,
      scale = 1,
    } = options;

    // 初始化所有子节点
    children.forEach((child, index) => {
      if (!isValid(child)) return;

      // 获取布局计算后的位置作为目标位置
      const targetPos = child.getPosition().clone();

      if (index < 8) {

        // 设置初始偏移位置，增加偏移量使动画更明显
        const startPos = new Vec3(
          targetPos.x + offsetX,
          targetPos.y +800,
          targetPos.z
        );
        child.setPosition(startPos);
        child.setScale(0.8, 0.8, 0.8);

        // 使用原始的DelayBezierMoveAndScale方法确保位置正确

        UIUtils.DelayBezierMoveAndScale(
          child,
          targetPos,
          scale,
          duration, 
          delayInterval * index
        ).then(() => {
          completedCount++;
          if (onItemComplete) onItemComplete(index, child);

          if (completedCount >= totalItems && callback) {
            callback();
          }
        });
      } else {
        child.setPosition(targetPos);
        child.setScale(1, 1, 1);
        child.active = true;
        if (onItemComplete) onItemComplete(index, child);

        if (completedCount >= totalItems && callback) {
          callback();
        }
      }
    });
  }

  static AnimScaleShake(
    node: Node,
    scale: number = 1.2,
    duration: number = 0.6,
    repeatForever: boolean = true,
    callback?: () => void
  ) {
    const originalScale = node.getScale().clone();

    const scaleUp = Vec3.multiplyScalar(new Vec3(), originalScale, scale);

    const animation = tween(node)
      .to(
        duration / 2,
        { scale: originalScale.clone().multiplyScalar(scale) },
        { easing: "quadOut" }
      )
      .to(duration / 2, { scale: originalScale }, { easing: "quadIn" });

    if (repeatForever) {
      animation.repeatForever().start();
    } else {
      animation
        .call(() => {
          if (callback) callback();
        })
        .start();
    }
  }

  static async AnimShakeUpAndDownByTimes(node: Node, duration: number) {
    // 根据动画的次数，计算出动画的间隔时间

    return new Promise((resolve, reject) => {
      tween(node)
        .to(
          duration / 2,
          { position: new Vec3(0, 30, 0) },
          { easing: "quadOut" }
        )
        .to(
          duration / 2,
          { position: new Vec3(0, 150, 0) },
          { easing: "quadIn" }
        )
        .call(() => {
          resolve(node);
        })
        .start();
    });
  }

  static MoveXY(
    node: Node,
    moveX: number,
    moveY: number,
    duration: number,
    delay: number
  ) {
    let toPosition = node.getPosition();
    node.setPosition(toPosition.x + moveX, toPosition.y + moveY, toPosition.z);

    this.DelayBezierMoveAndScale(node, toPosition, 1, duration, delay);
  }

  static async DelayBezierMoveAndScale(
    node: Node,
    targetPos: Vec3,
    scale: number,
    duration: number,
    delay: number
  ) {
    await new Promise((resolve) => setTimeout(resolve, delay));
    return new Promise((resolve, reject) => {
      this.AnimBezierMoveAndScale(node, targetPos, scale, duration, () => {
        resolve(node);
      });
    });
  }

  static fadeIn(child: Node, duration: number) {
    if (!isValid(child)) {
      return;
    }
    let opacityComp = child.getComponent(UIOpacity);
    if (!opacityComp) {
      opacityComp = child.addComponent(UIOpacity);
    }
    child.setScale(0, 0);
    tween({ t: 0 })
      .to(
        duration,
        { t: 1 },
        {
          easing: "quadInOut",
          onUpdate: (obj) => {
            if (!isValid(child)) {
              return;
            }
            child.setScale(1 * obj.t, 1 * obj.t);
            opacityComp.opacity = 255 * obj.t;
          },
        }
      )
      .start();
  }

  static AnimBezierMoveAndTranslate(
    node: Node,
    targetPos: Vec3,
    scale: number,
    duration: number,
    callback?: Function
  ) {
    if (!isValid(node)) {
      return;
    }

    let opacityComp = node.getComponent(UIOpacity);
    if (!opacityComp) {
      opacityComp = node.addComponent(UIOpacity);
    }
    const startPos = node.getPosition();
    const startScale = node.scale.clone();

    const ctrl = new Vec3(
      (startPos.x + targetPos.x) / 2,
      Math.max(startPos.y, targetPos.y) + 150,
      (startPos.z + targetPos.z) / 2
    );

    const tempPos = new Vec3();
    const tempScale = new Vec3();

    tween({ t: 0 })
      .to(
        duration,
        { t: 1 },
        {
          easing: "quadInOut",
          onUpdate: (obj) => {
            if (!isValid(node)) {
              return;
            }

            const t = obj.t;
            const oneMinusT = 1 - t;

            // 贝塞尔曲线计算
            tempPos.x =
              oneMinusT * oneMinusT * startPos.x +
              2 * t * oneMinusT * ctrl.x +
              t * t * targetPos.x;
            tempPos.y =
              oneMinusT * oneMinusT * startPos.y +
              2 * t * oneMinusT * ctrl.y +
              t * t * targetPos.y;
            tempPos.z =
              oneMinusT * oneMinusT * startPos.z +
              2 * t * oneMinusT * ctrl.z +
              t * t * targetPos.z;

            node.setPosition(tempPos);

            // 缩放插值计算
            tempScale.set(
              startScale.x + (scale - startScale.x) * t,
              startScale.y + (scale - startScale.y) * t,
              startScale.z + (scale - startScale.z) * t
            );

            node.setScale(tempScale);
            //设置透明度，越来越透明

            opacityComp.opacity = 255 * (1 - t);
          },
        }
      )
      .call(() => {
        if (callback) callback();
      })
      .start();
  }

  // 贝塞尔曲线实现移动和缩放动画
  static AnimBezierMoveAndScale(
    node: Node,
    targetPos: Vec3,
    scale: number,
    duration: number,
    callback?: Function,
    rotate?: number
  ) {
    if (!isValid(node)) {
      return;
    }
    const startPos = node.getPosition();
    const startScale = node.scale.clone();

    const ctrl = new Vec3(
      (startPos.x + targetPos.x) / 2,
      Math.max(startPos.y, targetPos.y) + 150,
      (startPos.z + targetPos.z) / 2
    );

    const tempPos = new Vec3();
    const tempScale = new Vec3();

    tween({ t: 0 })
      .to(
        duration,
        { t: 1 },
        {
          easing: "quadInOut",
          onUpdate: (obj) => {
            if (!isValid(node)) {
              return;
            }

            const t = obj.t;
            const oneMinusT = 1 - t;

            // 贝塞尔曲线计算
            tempPos.x =
              oneMinusT * oneMinusT * startPos.x +
              2 * t * oneMinusT * ctrl.x +
              t * t * targetPos.x;
            tempPos.y =
              oneMinusT * oneMinusT * startPos.y +
              2 * t * oneMinusT * ctrl.y +
              t * t * targetPos.y;
            tempPos.z =
              oneMinusT * oneMinusT * startPos.z +
              2 * t * oneMinusT * ctrl.z +
              t * t * targetPos.z;

            node.setPosition(tempPos);

            // 缩放插值计算
            tempScale.set(
              startScale.x + (scale - startScale.x) * t,
              startScale.y + (scale - startScale.y) * t,
              startScale.z + (scale - startScale.z) * t
            );

            node.setScale(tempScale);

            if (rotate) {
              node.setRotationFromEuler(new Vec3(0, 0, rotate * t));
            }
          },
        }
      )
      .call(() => {
        if (callback) callback();
      })
      .start();
  }

  public static _findInChildren(node: Node, name: string): Node {
    var x = node.getChildByName(name);
    if (x) return x;
    if (node.children.length == 0) return null;

    for (var i = 0; i < node.children.length; ++i) {
      var tmp = this._findInChildren(node.children[i], name);
      if (tmp) return tmp;
    }
    return null;
  }
}

/*
使用示例：

// 基本用法 - 滑入动画
UIUtils.AnimateLayoutItems(layoutNode);

// 自定义选项
UIUtils.AnimateLayoutItems(layoutNode, {
  duration: 0.5,
  delayInterval: 0.15,
  scale: 1.1,
  easing: 'backOut',
  staggerDirection: 'reverse'
}, () => {
  console.log('所有动画完成');
});

// 带单个项目完成回调
UIUtils.AnimateLayoutItems(layoutNode, {
  onItemComplete: (index, node) => {
    console.log(`第${index}个项目动画完成`);
  }
}, () => {
  console.log('所有项目动画完成');
});
*/
