// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

// THIS FILE WAS AUTO-GENERATED BY ./wpilibj/generate_hids.py. DO NOT MODIFY

package edu.wpi.first.wpilibj;

// import edu.wpi.first.hal.FRCNetComm.tResourceType;
// import edu.wpi.first.hal.HAL;
import edu.wpi.first.util.sendable.Sendable;
import edu.wpi.first.util.sendable.SendableBuilder;
import edu.wpi.first.wpilibj.event.BooleanEvent;
import edu.wpi.first.wpilibj.event.EventLoop;

/**
 * Handle input from PS5 controllers connected to the Driver Station.
 *
 * <p>This class handles PS5 input that comes from the Driver Station. Each time a value is
 * requested the most recent value is returned. There is a single class instance for each controller
 * and the mapping of ports to hardware buttons depends on the code in the Driver Station.
 *
 * <p>Only first party controllers from Sony are guaranteed to have the correct mapping, and
 * only through the official NI DS. Sim is not guaranteed to have the same mapping, as well as any
 * 3rd party controllers.
 */
public class PS5Controller extends GenericHID implements Sendable {
  /** Represents a digital button on a PS5Controller. */
  public enum Button {
    /** Square button. */
    kSquare(1),
    /** Cross button. */
    kCross(2),
    /** Circle button. */
    kCircle(3),
    /** Triangle button. */
    kTriangle(4),
    /** Left trigger 1 button. */
    kL1(5),
    /** Right trigger 1 button. */
    kR1(6),
    /** Left trigger 2 button. */
    kL2(7),
    /** Right trigger 2 button. */
    kR2(8),
    /** Create button. */
    kCreate(9),
    /** Options button. */
    kOptions(10),
    /** L3 (left stick) button. */
    kL3(11),
    /** R3 (right stick) button. */
    kR3(12),
    /** PlayStation button. */
    kPS(13),
    /** Touchpad button. */
    kTouchpad(14);

    /** Button value. */
    public final int value;

    Button(int value) {
      this.value = value;
    }

    /**
     * Get the human-friendly name of the button, matching the relevant methods. This is done by
     * stripping the leading `k`, and appending `Button`.
     *
     * <p>Primarily used for automated unit tests.
     *
     * @return the human-friendly name of the button.
     */
    @Override
    public String toString() {
      // Remove leading `k`
      return this.name().substring(1) + "Button";
    }
  }

  /** Represents an axis on an PS5Controller. */
  public enum Axis {
    /** Left X axis. */
    kLeftX(0),
    /** Left Y axis. */
    kLeftY(1),
    /** Right X axis. */
    kRightX(2),
    /** Right Y axis. */
    kRightY(5),
    /** Left trigger 2. */
    kL2(3),
    /** Right trigger 2. */
    kR2(4);

    /** Axis value. */
    public final int value;

    Axis(int value) {
      this.value = value;
    }

    /**
     * Get the human-friendly name of the axis, matching the relevant methods. This is done by
     * stripping the leading `k`, and appending `Axis` if the name ends with `2`.
     *
     * <p>Primarily used for automated unit tests.
     *
     * @return the human-friendly name of the axis.
     */
    @Override
    public String toString() {
      var name = this.name().substring(1); // Remove leading `k`
      if (name.endsWith("2")) {
        return name + "Axis";
      }
      return name;
    }
  }

  /**
   * Construct an instance of a controller.
   *
   * @param port The port index on the Driver Station that the controller is plugged into (0-5).
   */
  public PS5Controller(final int port) {
    super(port);
    // HAL.report(tResourceType.kResourceType_PS5Controller, port + 1);
  }

  /**
   * Get the X axis value of left side of the controller.
   *
   * @return The axis value.
   */
  public double getLeftX() {
    return getRawAxis(Axis.kLeftX.value);
  }

  /**
   * Get the Y axis value of left side of the controller.
   *
   * @return The axis value.
   */
  public double getLeftY() {
    return getRawAxis(Axis.kLeftY.value);
  }

  /**
   * Get the X axis value of right side of the controller.
   *
   * @return The axis value.
   */
  public double getRightX() {
    return getRawAxis(Axis.kRightX.value);
  }

  /**
   * Get the Y axis value of right side of the controller.
   *
   * @return The axis value.
   */
  public double getRightY() {
    return getRawAxis(Axis.kRightY.value);
  }

  /**
   * Get the left trigger 2 axis value of the controller. Note that this axis is bound to the
   * range of [0, 1] as opposed to the usual [-1, 1].
   *
   * @return The axis value.
   */
  public double getL2Axis() {
    return getRawAxis(Axis.kL2.value);
  }

  /**
   * Get the right trigger 2 axis value of the controller. Note that this axis is bound to the
   * range of [0, 1] as opposed to the usual [-1, 1].
   *
   * @return The axis value.
   */
  public double getR2Axis() {
    return getRawAxis(Axis.kR2.value);
  }

  /**
   * Read the value of the square button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getSquareButton() {
    return getRawButton(Button.kSquare.value);
  }

  /**
   * Whether the square button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getSquareButtonPressed() {
    return getRawButtonPressed(Button.kSquare.value);
  }

  /**
   * Whether the square button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getSquareButtonReleased() {
    return getRawButtonReleased(Button.kSquare.value);
  }

  /**
   * Constructs an event instance around the square button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the square button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent square(EventLoop loop) {
    return button(Button.kSquare.value, loop);
  }

  /**
   * Read the value of the cross button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getCrossButton() {
    return getRawButton(Button.kCross.value);
  }

  /**
   * Whether the cross button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getCrossButtonPressed() {
    return getRawButtonPressed(Button.kCross.value);
  }

  /**
   * Whether the cross button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getCrossButtonReleased() {
    return getRawButtonReleased(Button.kCross.value);
  }

  /**
   * Constructs an event instance around the cross button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the cross button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent cross(EventLoop loop) {
    return button(Button.kCross.value, loop);
  }

  /**
   * Read the value of the circle button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getCircleButton() {
    return getRawButton(Button.kCircle.value);
  }

  /**
   * Whether the circle button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getCircleButtonPressed() {
    return getRawButtonPressed(Button.kCircle.value);
  }

  /**
   * Whether the circle button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getCircleButtonReleased() {
    return getRawButtonReleased(Button.kCircle.value);
  }

  /**
   * Constructs an event instance around the circle button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the circle button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent circle(EventLoop loop) {
    return button(Button.kCircle.value, loop);
  }

  /**
   * Read the value of the triangle button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getTriangleButton() {
    return getRawButton(Button.kTriangle.value);
  }

  /**
   * Whether the triangle button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getTriangleButtonPressed() {
    return getRawButtonPressed(Button.kTriangle.value);
  }

  /**
   * Whether the triangle button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getTriangleButtonReleased() {
    return getRawButtonReleased(Button.kTriangle.value);
  }

  /**
   * Constructs an event instance around the triangle button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the triangle button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent triangle(EventLoop loop) {
    return button(Button.kTriangle.value, loop);
  }

  /**
   * Read the value of the left trigger 1 button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getL1Button() {
    return getRawButton(Button.kL1.value);
  }

  /**
   * Whether the left trigger 1 button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getL1ButtonPressed() {
    return getRawButtonPressed(Button.kL1.value);
  }

  /**
   * Whether the left trigger 1 button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getL1ButtonReleased() {
    return getRawButtonReleased(Button.kL1.value);
  }

  /**
   * Constructs an event instance around the left trigger 1 button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the left trigger 1 button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent L1(EventLoop loop) {
    return button(Button.kL1.value, loop);
  }

  /**
   * Read the value of the right trigger 1 button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getR1Button() {
    return getRawButton(Button.kR1.value);
  }

  /**
   * Whether the right trigger 1 button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getR1ButtonPressed() {
    return getRawButtonPressed(Button.kR1.value);
  }

  /**
   * Whether the right trigger 1 button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getR1ButtonReleased() {
    return getRawButtonReleased(Button.kR1.value);
  }

  /**
   * Constructs an event instance around the right trigger 1 button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the right trigger 1 button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent R1(EventLoop loop) {
    return button(Button.kR1.value, loop);
  }

  /**
   * Read the value of the left trigger 2 button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getL2Button() {
    return getRawButton(Button.kL2.value);
  }

  /**
   * Whether the left trigger 2 button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getL2ButtonPressed() {
    return getRawButtonPressed(Button.kL2.value);
  }

  /**
   * Whether the left trigger 2 button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getL2ButtonReleased() {
    return getRawButtonReleased(Button.kL2.value);
  }

  /**
   * Constructs an event instance around the left trigger 2 button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the left trigger 2 button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent L2(EventLoop loop) {
    return button(Button.kL2.value, loop);
  }

  /**
   * Read the value of the right trigger 2 button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getR2Button() {
    return getRawButton(Button.kR2.value);
  }

  /**
   * Whether the right trigger 2 button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getR2ButtonPressed() {
    return getRawButtonPressed(Button.kR2.value);
  }

  /**
   * Whether the right trigger 2 button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getR2ButtonReleased() {
    return getRawButtonReleased(Button.kR2.value);
  }

  /**
   * Constructs an event instance around the right trigger 2 button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the right trigger 2 button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent R2(EventLoop loop) {
    return button(Button.kR2.value, loop);
  }

  /**
   * Read the value of the create button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getCreateButton() {
    return getRawButton(Button.kCreate.value);
  }

  /**
   * Whether the create button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getCreateButtonPressed() {
    return getRawButtonPressed(Button.kCreate.value);
  }

  /**
   * Whether the create button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getCreateButtonReleased() {
    return getRawButtonReleased(Button.kCreate.value);
  }

  /**
   * Constructs an event instance around the create button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the create button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent create(EventLoop loop) {
    return button(Button.kCreate.value, loop);
  }

  /**
   * Read the value of the options button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getOptionsButton() {
    return getRawButton(Button.kOptions.value);
  }

  /**
   * Whether the options button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getOptionsButtonPressed() {
    return getRawButtonPressed(Button.kOptions.value);
  }

  /**
   * Whether the options button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getOptionsButtonReleased() {
    return getRawButtonReleased(Button.kOptions.value);
  }

  /**
   * Constructs an event instance around the options button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the options button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent options(EventLoop loop) {
    return button(Button.kOptions.value, loop);
  }

  /**
   * Read the value of the L3 (left stick) button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getL3Button() {
    return getRawButton(Button.kL3.value);
  }

  /**
   * Whether the L3 (left stick) button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getL3ButtonPressed() {
    return getRawButtonPressed(Button.kL3.value);
  }

  /**
   * Whether the L3 (left stick) button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getL3ButtonReleased() {
    return getRawButtonReleased(Button.kL3.value);
  }

  /**
   * Constructs an event instance around the L3 (left stick) button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the L3 (left stick) button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent L3(EventLoop loop) {
    return button(Button.kL3.value, loop);
  }

  /**
   * Read the value of the R3 (right stick) button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getR3Button() {
    return getRawButton(Button.kR3.value);
  }

  /**
   * Whether the R3 (right stick) button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getR3ButtonPressed() {
    return getRawButtonPressed(Button.kR3.value);
  }

  /**
   * Whether the R3 (right stick) button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getR3ButtonReleased() {
    return getRawButtonReleased(Button.kR3.value);
  }

  /**
   * Constructs an event instance around the R3 (right stick) button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the R3 (right stick) button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent R3(EventLoop loop) {
    return button(Button.kR3.value, loop);
  }

  /**
   * Read the value of the PlayStation button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getPSButton() {
    return getRawButton(Button.kPS.value);
  }

  /**
   * Whether the PlayStation button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getPSButtonPressed() {
    return getRawButtonPressed(Button.kPS.value);
  }

  /**
   * Whether the PlayStation button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getPSButtonReleased() {
    return getRawButtonReleased(Button.kPS.value);
  }

  /**
   * Constructs an event instance around the PlayStation button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the PlayStation button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent PS(EventLoop loop) {
    return button(Button.kPS.value, loop);
  }

  /**
   * Read the value of the touchpad button on the controller.
   *
   * @return The state of the button.
   */
  public boolean getTouchpadButton() {
    return getRawButton(Button.kTouchpad.value);
  }

  /**
   * Whether the touchpad button was pressed since the last check.
   *
   * @return Whether the button was pressed since the last check.
   */
  public boolean getTouchpadButtonPressed() {
    return getRawButtonPressed(Button.kTouchpad.value);
  }

  /**
   * Whether the touchpad button was released since the last check.
   *
   * @return Whether the button was released since the last check.
   */
  public boolean getTouchpadButtonReleased() {
    return getRawButtonReleased(Button.kTouchpad.value);
  }

  /**
   * Constructs an event instance around the touchpad button's digital signal.
   *
   * @param loop the event loop instance to attach the event to.
   * @return an event instance representing the touchpad button's digital signal
   *     attached to the given loop.
   */
  public BooleanEvent touchpad(EventLoop loop) {
    return button(Button.kTouchpad.value, loop);
  }

  /**
   * Read the value of the touchpad on the controller.
   *
   * @return The state of the touchpad.
   * @deprecated Use {@link getTouchpadButton} instead. This function is deprecated for removal to
   *     make function names consistent to allow the HID classes to be automatically generated.
   */
  @Deprecated(since = "2025", forRemoval = true)
  public boolean getTouchpad() {
    return getRawButton(Button.kTouchpad.value);
  }

  /**
   * Whether the touchpad was pressed since the last check.
   *
   * @return Whether the touchpad was pressed since the last check.
   * @deprecated Use {@link getTouchpadButtonPressed} instead. This function is deprecated for
   *     removal to make function names consistent to allow the HID classes to be automatically
   *     generated.
   */
  @Deprecated(since = "2025", forRemoval = true)
  public boolean getTouchpadPressed() {
    return getRawButtonPressed(Button.kTouchpad.value);
  }

  /**
   * Whether the touchpad was released since the last check.
   *
   * @return Whether the touchpad was released since the last check.
   * @deprecated Use {@link getTouchpadButtonReleased} instead. This function is deprecated for
   *     removal to make function names consistent to allow the HID classes to be automatically
   *     generated.
   */
  @Deprecated(since = "2025", forRemoval = true)
  public boolean getTouchpadReleased() {
    return getRawButtonReleased(Button.kTouchpad.value);
  }

  @Override
  public void initSendable(SendableBuilder builder) {
    builder.setSmartDashboardType("HID");
    builder.publishConstString("ControllerType", "PS5");
    builder.addDoubleProperty("L2", this::getL2Axis, null);
    builder.addDoubleProperty("R2", this::getR2Axis, null);
    builder.addDoubleProperty("LeftX", this::getLeftX, null);
    builder.addDoubleProperty("LeftY", this::getLeftY, null);
    builder.addDoubleProperty("RightX", this::getRightX, null);
    builder.addDoubleProperty("RightY", this::getRightY, null);
    builder.addBooleanProperty("Square", this::getSquareButton, null);
    builder.addBooleanProperty("Cross", this::getCrossButton, null);
    builder.addBooleanProperty("Circle", this::getCircleButton, null);
    builder.addBooleanProperty("Triangle", this::getTriangleButton, null);
    builder.addBooleanProperty("L1", this::getL1Button, null);
    builder.addBooleanProperty("R1", this::getR1Button, null);
    builder.addBooleanProperty("L2", this::getL2Button, null);
    builder.addBooleanProperty("R2", this::getR2Button, null);
    builder.addBooleanProperty("Create", this::getCreateButton, null);
    builder.addBooleanProperty("Options", this::getOptionsButton, null);
    builder.addBooleanProperty("L3", this::getL3Button, null);
    builder.addBooleanProperty("R3", this::getR3Button, null);
    builder.addBooleanProperty("PS", this::getPSButton, null);
    builder.addBooleanProperty("Touchpad", this::getTouchpadButton, null);
  }
}
