import {
  isValid,
  Node,
  Component,
  find,
  Button,
  Color,
  Label,
  Event,
  SpriteFrame,
  Animation,
  Sprite,
  Vec3,
} from "cc";
import AB from "./AB";
import { tween } from "cc";

export default class BaseUI extends Component {
  public onHide() {}
  public onShow() {}
  private m_objects: Map<string, Node> = new Map<string, Node>();

  protected setButtonEnable(name: string, enable: boolean) {
    if (!isValid(this.node)) {
      return;
    }
    this.FindAs(name, Sprite).grayscale = !enable;
    this.FindButton(name).interactable = enable;
  }

  public FindAs<T extends Component>(
    name: string,
    type: new (...args: any[]) => T
  ): T {
    const node = this.FindNode(name);
    if (!node) return null;
    return node.getComponent(type);
  }

  public FindLabel(name: string): Label {
    return this.FindAs(name, Label);
  }

  public FindButton(name: string): Button {
    return this.FindAs(name, Button);
  }

  public async setText(nodeName: string, text: string): Promise<void> {
    const node = this.FindAs<Label>(nodeName, Label);
    if (!node) {
      console.warn("setText", nodeName, "not found");
      return;
    }
    node.string = text;
    await Promise.resolve();
  }
  public async SetSprite(nodeName: string, spritePath: string): Promise<void> {
    const sp: SpriteFrame = await AB.ins.loadSpriteFrame(spritePath);
    const node = this.FindAs<Sprite>(nodeName, Sprite);
    node.spriteFrame = sp;
  }

  public FindNode(name: string, node: Node = null): Node {
    if (!isValid(this.node)) {
      return;
    }

    if (this.m_objects == null) {
      return null;
    }

    // 检查缓存
    // 检查缓存
    if (this.m_objects.has(name)) {
      const cachedNode = this.m_objects.get(name);
      if (isValid(cachedNode)) return cachedNode;
      this.m_objects.delete(name);
    }

    // 设置起始节点
    node = isValid(node) ? node : this.node;
    if (!isValid(node)) return null;

    // 检查当前节点
    if (node.name == name) {
      this.m_objects.set(name, node);
      return node;
    }

    // 递归查找子节点
    for (const child of node.children) {
      const result = this.FindNode(name, child);
      if (result) {
        this.m_objects.set(name, result);
        return result;
      }
    }

    return null;
  }

  protected onLoad(): void {
    console.log("BaseUI onLoad:", this.node.name);
    this.deepScanChildAndFindButtons(this.node);
  }

  private _onBtnClick(event: Event, customEventData: string): void {
    const target = event.target as unknown as Node;
    const name = target.name;
    console.log("按钮点击", name);
    this.onBtnClick(name, event, customEventData);
    if (name != "btn_close") {
      this.simpleOnBtnClick(name);
      console.log("simpleOnBtnClick", name);

    }
  }
  protected onBtnClick(name: string, event: Event, customEventData: any) {
    if (name == "btn_close") {
      this.closePage();
    }
  }
  protected simpleOnBtnClick(name: string) {}

  protected canClose: boolean = true;

  protected closePage() {
    if (!this.canClose) {
      return;
    }

    let isAnim = false;
    // let bg = this.FindNode("bg");
    // if (bg != null) {
    //   // scale 0.5
    //   tween(bg)
    //     .to(0.1, { scale: new Vec3(1.2, 1.2, 1) })
    //     .to(0.3, { scale: new Vec3(0, 0, 1) })
    //     .start();
    //   isAnim = true;
    // }

    if (this.m_objects != null) {
      this.m_objects.clear();
    }
    this.m_objects = null;

    let self = this;
    if (!isAnim) {
      self.node.destroy();
    } else {
      setTimeout(() => {
        if (isValid(self.node)) {
          self.node.destroy();
        }
      }, 1000);
    }
  }

  protected deepScanChildAndFindButtons(node: Node): void {
    // console.log("扫描节点:", node.name);
    // 如果节点是BaseUI，并且不是当前节点，则不扫描
    if (
      node.getComponent(BaseUI) &&
      node.getComponent(BaseUI).node != this.node
    ) {
      return;
    }

    if (node.name.startsWith("btn_")) {
      const button = node.getComponent(Button);
      if (!button) {
        let btn = node.addComponent(Button);
        btn.transition = Button.Transition.COLOR;

        btn.normalColor = new Color("#ffffff");
        btn.hoverColor = new Color("#D3D3D3");
        btn.pressedColor = new Color("#D3D3D3");
        btn.disabledColor = new Color("#ffffff");
      }
      node.on(Button.EventType.CLICK, this._onBtnClick, this);
    }

    node.children.forEach((child) => {
      this.deepScanChildAndFindButtons(child);
    });
  }
}

// type Constructor<T> = new (...args: any[]) => T;
