import { _decorator, Node, UITransform, v3, v2, misc, Component, EventTouch, Vec2 } from "cc";

const { ccclass, property } = _decorator;

/**
 * 角度控制按钮组件
 */
@ccclass("Joystick")
export class Joystick extends Component {

  @property(Node)
  private handle: Node = null;

  private maxRadius = 100;

  /** 方向向量 */
  private dir: Vec2 = v2(0, 0);

  /** 当前角度 */
  public angle: number = 0;

  onLoad() {

    this.maxRadius = this.getComponent(UITransform).contentSize.width / 2;

    // 注册触摸事件
    this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this);
    this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
    this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
    this.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
  }

  /**
   * 触摸开始回调
   */
  onTouchStart(event: EventTouch) {
    this.calcPos(event.getUILocation());
  }

  /**
   * 触摸移动回调
   */
  onTouchMove(event: EventTouch) {
    this.calcPos(event.getUILocation());
  }

  /**
   * 触摸结束回调
   */
  onTouchEnd(event: EventTouch) {
    // 重置方向和圆点位置
    this.dir.x = this.dir.y = 0;
    this.handle.setPosition(0, 0);
  }

  /**
   * 计算圆点位置和角度
   */
  calcPos = (() => {
    const worldPos = v3();
    const nodePos = v3();

    return (pos: Vec2) => {

      worldPos.x = pos.x;
      worldPos.y = pos.y;

      // 转换到节点本地坐标
      this.getComponent(UITransform).convertToNodeSpaceAR(worldPos, nodePos);
      nodePos.z = 0;

      // 计算长度并限制在最大半径内
      const len = nodePos.length();
      if (len > this.maxRadius) {
        nodePos.multiplyScalar(this.maxRadius / len);
      }

      this.handle.setPosition(nodePos);

      nodePos.normalize();

      this.dir.set(nodePos.x, nodePos.y);

      // 计算角度
      this.angle = this.vectorsToDegree(this.dir);
    };
  })();

  /**
   * 向量转角度
   */
  vectorsToDegree(vector: Vec2): number {
    const right = v2(1, 0);
    const radian = vector.signAngle(right);
    return misc.radiansToDegrees(radian);
  }
}