export var TouchDirection;
(function (TouchDirection) {
  TouchDirection["RIGHT"] = "TOUCH_DIR_RIGHT";
  TouchDirection["LEFT"] = "TOUCH_DIR_LEFT";
  TouchDirection["UP"] = "TOUCH_DIR_UP";
  TouchDirection["DOWN"] = "TOUCH_DIR_DOWN";
})(TouchDirection || (TouchDirection = {}));
/**
 * The TouchListener class is a class that listens for touch events on a touchable element
 * and calls a callback function when a touch event occurs
 *
 * @property {TouchListenerInitParams} TouchListenerInitParams params for create touch listener
 * @property {{ x: number; y: number }} touchStartState state object to record start touch coordinate
 */
export class TouchListener {
  /**
   * Create a new instance of the TouchListener class
   *
   * @param {TouchListenerInitParams} params - TouchListenerInitParams
   */
  constructor(params) {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    this.touchStart = this.onTouchStart.bind(this);
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    this.touchMove = this.onTouchMove.bind(this);
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    this.touchEnd = this.onTouchEnd.bind(this);
    this.touchableParams = params;
    this.attachListeners();
  }
  /**
   * It creates a new instance of the TouchListener class
   *
   * @param {TouchListenerInitParams} params - TouchListenerInitParams
   * @returns {TouchListener} A new instance of the TouchListener class.
   */
  static init(params) {
    return new TouchListener(params);
  }
  /**
   * Given the start and end coordinates of a touch event, return the direction and distance of the touch
   *
   * @param {number} startX - The x coordinate of the touch start event.
   * @param {number} startY - The y-coordinate of the touch start event.
   * @param {number} endX - The x coordinate of the touch end event.
   * @param {number} endY - the y coordinate of the touch event.
   * @returns {TouchDirectionAndDistanceType} The direction and distance of the touch.
   */
  static getTouchDirectionAndDistance(startX, startY, endX, endY) {
    const delX = endX - startX;
    const delY = endY - startY;
    if (Math.abs(delX) > Math.abs(delY)) {
      return {
        direction: delX > 0 ? TouchDirection.RIGHT : TouchDirection.LEFT,
        distance: Math.abs(delX),
      };
    }
    else {
      return {
        direction: delY > 0 ? TouchDirection.UP : TouchDirection.DOWN,
        distance: Math.abs(delY),
      };
    }
  }
  /**
   * Get the coordinates of a touch event
   *
   * @param {TouchEvent} event - The event object that was passed to the handler.
   * @returns {TouchEventCoordinatesType} The coordinates of the touch event.
   */
  static getTouchEventCoordinates(event) {
    return { x: event.changedTouches[0].screenX, y: event.changedTouches[0].screenY };
  }
  /**
   * It removes the touchable events from the touchable.
   */
  destroy() {
    this.touchableParams.touchable.removeEventListener('touchstart', this.touchStart);
    this.touchableParams.touchable.removeEventListener('touchmove', this.touchMove);
    this.touchableParams.touchable.removeEventListener('touchend', this.touchEnd);
  }
  /**
   * Attach the touchstart, touchmove, and touchend listeners to the touchable element.
   * The bind() method returns a copy of the given function with the provided this value and initial arguments,
   * which causes remove event listeners to fail.
   */
  attachListeners() {
    this.touchableParams.touchable.addEventListener('touchstart', this.touchStart);
    this.touchableParams.touchable.addEventListener('touchmove', this.touchMove);
    this.touchableParams.touchable.addEventListener('touchend', this.touchEnd);
  }
  /**
   * It prevents the default behavior of the touch event and stores the coordinates of the touch event in the
   * touchStartState variable.
   *
   * @param {TouchEvent} event - The event object that was triggered.
   */
  onTouchStart(event) {
    var _a, _b;
    this.touchStartState = TouchListener.getTouchEventCoordinates(event);
    (_b = (_a = this.touchableParams).onTouchStart) === null || _b === void 0 ? void 0 : _b.call(_a, this.touchStartState.x, this.touchStartState.y);
  }
  /**
   * It prevents the default behavior of the event, and then it gets the coordinates of the touch event, and then it gets
   * the direction and distance of the touch event.
   *
   * @param {TouchEvent} event - The native event object.
   */
  onTouchMove(event) {
    var _a, _b;
    const { x, y } = TouchListener.getTouchEventCoordinates(event);
    const { direction, distance } = TouchListener.getTouchDirectionAndDistance(this.touchStartState.x, this.touchStartState.y, x, y);
    (_b = (_a = this.touchableParams).onTouchMove) === null || _b === void 0 ? void 0 : _b.call(_a, direction, distance);
  }
  /**
   * It calls the onTouchEnd function of the touchableParams object.
   *
   * @param {TouchEvent} event - The event object that was passed to the onTouchStart or onTouchEnd callback.
   */
  onTouchEnd(event) {
    var _a, _b;
    const { x, y } = TouchListener.getTouchEventCoordinates(event);
    const { direction } = TouchListener.getTouchDirectionAndDistance(this.touchStartState.x, this.touchStartState.y, x, y);
    (_b = (_a = this.touchableParams).onTouchEnd) === null || _b === void 0 ? void 0 : _b.call(_a, direction);
    this.resetStartState();
  }
  /**
   * Reset the start state
   */
  resetStartState() {
    this.touchStartState = { x: 0, y: 0 };
  }
}
