import {
  _decorator,
  Animation,
  Button,
  Component,
  EditBox,
  editorExtrasTag,
  find,
  isValid,
  js,
  Label,
  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";
import AB from "./AB";

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

  // static async addEmptyNode(layout: Node) {
  //   let p = await Utils.loadRes("v2/ui/items/EmptyNode", Prefab);
  //   let emptyNode = instantiate(p as unknown as Prefab);
  //   emptyNode.active = true;
  //   emptyNode.name = "EmptyNode";
  //   emptyNode.parent = layout;
  // }

  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);
  }

  static AnimateLayoutItems(
    layout: Node,
    offsetX: number = -20,
    offsetY: number = -20,
    delayInterval: number = 0.1,
    duration: number = 0.3
  ): void {
    const children = layout.children;

    children.forEach((child, index) => {
      // 记录原始位置并设置初始偏移位置
      const originalPos = child.position.clone();
      child.setPosition(
        originalPos.x + offsetX,
        originalPos.y + offsetY,
        originalPos.z
      );

      // 设置透明度组件
      let opacityComp = child.getComponent(UIOpacity);
      if (!opacityComp) {
        opacityComp = child.addComponent(UIOpacity);
      }
      opacityComp.opacity = 0;

      // 启动动画
      tween(child)
        .delay(index * delayInterval)
        .parallel(
          tween(child).to(
            duration,
            { position: originalPos },
            { easing: "sineOut" }
          ),
          tween(opacityComp).to(duration, { opacity: 255 })
        )
        .start();
    });
  }

  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 async AsyncBezierMoveAndScale(
    node: Node,
    targetPos: Vec3,
    scale: number,
    duration: number,
    rotate?: number
  ) {
    return new Promise((resolve, reject) => {
      this.AnimBezierMoveAndScale(
        node,
        targetPos,
        scale,
        duration,
        () => {
          resolve(node);
        },
        rotate
      );
    });
  }
  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;
  }

  public static async SetSprite(
    sprite: Sprite,
    filepath: string,
    cb: Function
  ) {
    return new Promise((resolve, reject) => {
      if (sprite) {
        AB.ins
          .loadRes(filepath + "/spriteFrame", SpriteFrame)
          .then((ret: SpriteFrame) => {
            if (isValid(sprite.node)) {
              sprite.spriteFrame = ret;
              resolve(null);
              cb();
            } else {
            }
          })
          .catch((e) => {
            console.log(filepath);
            console.log(e);
          });
      }
    });
  }
}
