#include <unistd.h>

#include <array>
#include <chrono>
#include <cinttypes>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <functional>
#include <memory>
#include <mutex>
#include <thread>

#include "ctre/phoenix/CANifier.h"
#include "frc971/wpilib/ahal/AnalogInput.h"
#include "frc971/wpilib/ahal/Counter.h"
#include "frc971/wpilib/ahal/DigitalGlitchFilter.h"
#include "frc971/wpilib/ahal/DriverStation.h"
#include "frc971/wpilib/ahal/Encoder.h"
#include "frc971/wpilib/ahal/Servo.h"
#include "frc971/wpilib/ahal/TalonFX.h"
#include "frc971/wpilib/ahal/VictorSP.h"
#undef ERROR

#include "aos/commonmath.h"
#include "aos/containers/sized_array.h"
#include "aos/events/event_loop.h"
#include "aos/events/shm_event_loop.h"
#include "aos/init.h"
#include "aos/logging/logging.h"
#include "aos/realtime.h"
#include "aos/time/time.h"
#include "aos/util/log_interval.h"
#include "aos/util/phased_loop.h"
#include "aos/util/wrapping_counter.h"
#include "ctre/phoenix/cci/Diagnostics_CCI.h"
#include "ctre/phoenix/motorcontrol/can/TalonFX.h"
#include "ctre/phoenix/motorcontrol/can/TalonSRX.h"
#include "ctre/phoenixpro/TalonFX.hpp"
#include "frc971/autonomous/auto_mode_generated.h"
#include "frc971/control_loops/drivetrain/drivetrain_position_generated.h"
#include "frc971/input/robot_state_generated.h"
#include "frc971/queues/gyro_generated.h"
#include "frc971/wpilib/ADIS16448.h"
#include "frc971/wpilib/buffered_pcm.h"
#include "frc971/wpilib/buffered_solenoid.h"
#include "frc971/wpilib/dma.h"
#include "frc971/wpilib/drivetrain_writer.h"
#include "frc971/wpilib/encoder_and_potentiometer.h"
#include "frc971/wpilib/joystick_sender.h"
#include "frc971/wpilib/logging_generated.h"
#include "frc971/wpilib/loop_output_handler.h"
#include "frc971/wpilib/pdp_fetcher.h"
#include "frc971/wpilib/sensor_reader.h"
#include "frc971/wpilib/wpilib_robot_base.h"
#include "y2023/constants.h"
#include "y2023/control_loops/drivetrain/drivetrain_can_position_generated.h"
#include "y2023/control_loops/superstructure/superstructure_output_generated.h"
#include "y2023/control_loops/superstructure/superstructure_position_generated.h"

DEFINE_bool(ctre_diag_server, false,
            "If true, enable the diagnostics server for interacting with "
            "devices on the CAN bus using Phoenix Tuner");

using ::aos::monotonic_clock;
using ::y2023::constants::Values;
namespace superstructure = ::y2023::control_loops::superstructure;
namespace drivetrain = ::y2023::control_loops::drivetrain;
namespace chrono = ::std::chrono;
using std::make_unique;

namespace y2023 {
namespace wpilib {
namespace {

constexpr double kMaxBringupPower = 12.0;

// TODO(Brian): Fix the interpretation of the result of GetRaw here and in the
// DMA stuff and then removing the * 2.0 in *_translate.
// The low bit is direction.

double drivetrain_velocity_translate(double in) {
  return (((1.0 / in) / Values::kDrivetrainCyclesPerRevolution()) *
          (2.0 * M_PI)) *
         Values::kDrivetrainEncoderRatio() *
         control_loops::drivetrain::kWheelRadius;
}

double proximal_pot_translate(double voltage) {
  return voltage * Values::kProximalPotRadiansPerVolt();
}

double distal_pot_translate(double voltage) {
  return voltage * Values::kDistalPotRadiansPerVolt();
}

double roll_joint_pot_translate(double voltage) {
  return voltage * Values::kRollJointPotRadiansPerVolt();
}

constexpr double kMaxFastEncoderPulsesPerSecond = std::max({
    Values::kMaxDrivetrainEncoderPulsesPerSecond(),
    Values::kMaxProximalEncoderPulsesPerSecond(),
    Values::kMaxDistalEncoderPulsesPerSecond(),
    Values::kMaxRollJointEncoderPulsesPerSecond(),
    Values::kMaxWristEncoderPulsesPerSecond(),
});
static_assert(kMaxFastEncoderPulsesPerSecond <= 1300000,
              "fast encoders are too fast");

}  // namespace

static constexpr int kCANFalconCount = 6;
static constexpr int kCANSignalsCount = 4;
static constexpr int kRollerSignalsCount = 4;
static constexpr units::frequency::hertz_t kCANUpdateFreqHz = 200_Hz;

class Falcon {
 public:
  Falcon(int device_id, std::string canbus,
         aos::SizedArray<ctre::phoenixpro::BaseStatusSignalValue *,
                         kCANFalconCount * kCANSignalsCount +
                             kRollerSignalsCount> *signals)
      : talon_(device_id, canbus),
        device_id_(device_id),
        device_temp_(talon_.GetDeviceTemp()),
        supply_voltage_(talon_.GetSupplyVoltage()),
        supply_current_(talon_.GetSupplyCurrent()),
        torque_current_(talon_.GetTorqueCurrent()),
        position_(talon_.GetPosition()) {
    // device temp is not timesynced so don't add it to the list of signals
    device_temp_.SetUpdateFrequency(kCANUpdateFreqHz);

    CHECK_EQ(kCANSignalsCount, 4);
    CHECK_NOTNULL(signals);
    CHECK_LE(signals->size() + 4u, signals->capacity());

    supply_voltage_.SetUpdateFrequency(kCANUpdateFreqHz);
    signals->push_back(&supply_voltage_);

    supply_current_.SetUpdateFrequency(kCANUpdateFreqHz);
    signals->push_back(&supply_current_);

    torque_current_.SetUpdateFrequency(kCANUpdateFreqHz);
    signals->push_back(&torque_current_);

    position_.SetUpdateFrequency(kCANUpdateFreqHz);
    signals->push_back(&position_);
  }

  void WriteConfigs(ctre::phoenixpro::signals::InvertedValue invert) {
    inverted_ = invert;

    ctre::phoenixpro::configs::CurrentLimitsConfigs current_limits;
    current_limits.StatorCurrentLimit =
        constants::Values::kDrivetrainStatorCurrentLimit();
    current_limits.StatorCurrentLimitEnable = true;
    current_limits.SupplyCurrentLimit =
        constants::Values::kDrivetrainSupplyCurrentLimit();
    current_limits.SupplyCurrentLimitEnable = true;

    ctre::phoenixpro::configs::MotorOutputConfigs output_configs;
    output_configs.NeutralMode =
        ctre::phoenixpro::signals::NeutralModeValue::Brake;
    output_configs.DutyCycleNeutralDeadband = 0;

    output_configs.Inverted = inverted_;

    ctre::phoenixpro::configs::TalonFXConfiguration configuration;
    configuration.CurrentLimits = current_limits;
    configuration.MotorOutput = output_configs;

    ctre::phoenix::StatusCode status =
        talon_.GetConfigurator().Apply(configuration);
    if (!status.IsOK()) {
      AOS_LOG(ERROR, "Failed to set falcon configuration: %s: %s",
              status.GetName(), status.GetDescription());
    }
  }

  void WriteRollerConfigs() {
    ctre::phoenixpro::configs::CurrentLimitsConfigs current_limits;
    current_limits.StatorCurrentLimit =
        constants::Values::kRollerStatorCurrentLimit();
    current_limits.StatorCurrentLimitEnable = true;
    current_limits.SupplyCurrentLimit =
        constants::Values::kRollerSupplyCurrentLimit();
    current_limits.SupplyCurrentLimitEnable = true;

    ctre::phoenixpro::configs::MotorOutputConfigs output_configs;
    output_configs.NeutralMode =
        ctre::phoenixpro::signals::NeutralModeValue::Brake;
    output_configs.DutyCycleNeutralDeadband = 0;

    ctre::phoenixpro::configs::TalonFXConfiguration configuration;
    configuration.CurrentLimits = current_limits;
    configuration.MotorOutput = output_configs;

    ctre::phoenix::StatusCode status =
        talon_.GetConfigurator().Apply(configuration);
    if (!status.IsOK()) {
      AOS_LOG(ERROR, "Failed to set falcon configuration: %s: %s",
              status.GetName(), status.GetDescription());
    }
  }

  ctre::phoenixpro::hardware::TalonFX *talon() { return &talon_; }

  flatbuffers::Offset<drivetrain::CANFalcon> WritePosition(
      flatbuffers::FlatBufferBuilder *fbb) {
    drivetrain::CANFalcon::Builder builder(*fbb);
    builder.add_id(device_id_);
    builder.add_device_temp(device_temp());
    builder.add_supply_voltage(supply_voltage());
    builder.add_supply_current(supply_current());
    builder.add_torque_current(torque_current());

    double invert =
        (inverted_ ==
                 ctre::phoenixpro::signals::InvertedValue::Clockwise_Positive
             ? 1
             : -1);

    builder.add_position(
        constants::Values::DrivetrainCANEncoderToMeters(position()) * invert);

    return builder.Finish();
  }

  int device_id() const { return device_id_; }
  float device_temp() const { return device_temp_.GetValue().value(); }
  float supply_voltage() const { return supply_voltage_.GetValue().value(); }
  float supply_current() const { return supply_current_.GetValue().value(); }
  float torque_current() const { return torque_current_.GetValue().value(); }
  float position() const { return position_.GetValue().value(); }

  // returns the monotonic timestamp of the latest timesynced reading in the
  // timebase of the the syncronized CAN bus clock.
  int64_t GetTimestamp() {
    std::chrono::nanoseconds latest_timestamp =
        torque_current_.GetTimestamp().GetTime();

    return latest_timestamp.count();
  }

  void RefreshNontimesyncedSignals() { device_temp_.Refresh(); };

 private:
  ctre::phoenixpro::hardware::TalonFX talon_;
  int device_id_;

  ctre::phoenixpro::signals::InvertedValue inverted_;

  ctre::phoenixpro::StatusSignalValue<units::temperature::celsius_t>
      device_temp_;
  ctre::phoenixpro::StatusSignalValue<units::voltage::volt_t> supply_voltage_;
  ctre::phoenixpro::StatusSignalValue<units::current::ampere_t> supply_current_,
      torque_current_;
  ctre::phoenixpro::StatusSignalValue<units::angle::turn_t> position_;
};

class CANSensorReader {
 public:
  CANSensorReader(aos::EventLoop *event_loop)
      : event_loop_(event_loop),
        can_position_sender_(
            event_loop->MakeSender<drivetrain::CANPosition>("/drivetrain")),
        roller_falcon_data_(std::nullopt) {
    event_loop->SetRuntimeRealtimePriority(40);
    event_loop->SetRuntimeAffinity(aos::MakeCpusetFromCpus({1}));
    timer_handler_ = event_loop->AddTimer([this]() { Loop(); });
    timer_handler_->set_name("CANSensorReader Loop");

    event_loop->OnRun([this]() {
      timer_handler_->Setup(event_loop_->monotonic_now(), 1 / kCANUpdateFreqHz);
    });
  }

  aos::SizedArray<ctre::phoenixpro::BaseStatusSignalValue *,
                  kCANFalconCount * kCANSignalsCount + kRollerSignalsCount>
      *get_signals_registry() {
    return &signals_;
  };

  void set_falcons(std::shared_ptr<Falcon> right_front,
                   std::shared_ptr<Falcon> right_back,
                   std::shared_ptr<Falcon> right_under,
                   std::shared_ptr<Falcon> left_front,
                   std::shared_ptr<Falcon> left_back,
                   std::shared_ptr<Falcon> left_under,
                   std::shared_ptr<Falcon> roller_falcon) {
    right_front_ = std::move(right_front);
    right_back_ = std::move(right_back);
    right_under_ = std::move(right_under);
    left_front_ = std::move(left_front);
    left_back_ = std::move(left_back);
    left_under_ = std::move(left_under);
    roller_falcon_ = std::move(roller_falcon);
  }

  std::optional<superstructure::CANFalconT> roller_falcon_data() {
    std::unique_lock<aos::stl_mutex> lock(roller_mutex_);
    return roller_falcon_data_;
  }

 private:
  void Loop() {
    CHECK_EQ(signals_.size(), 28u);
    ctre::phoenix::StatusCode status =
        ctre::phoenixpro::BaseStatusSignalValue::WaitForAll(
            2000_ms, {signals_[0],  signals_[1],  signals_[2],  signals_[3],
                      signals_[4],  signals_[5],  signals_[6],  signals_[7],
                      signals_[8],  signals_[9],  signals_[10], signals_[11],
                      signals_[12], signals_[13], signals_[14], signals_[15],
                      signals_[16], signals_[17], signals_[18], signals_[19],
                      signals_[20], signals_[21], signals_[22], signals_[23],
                      signals_[24], signals_[25], signals_[26], signals_[27]});

    if (!status.IsOK()) {
      AOS_LOG(ERROR, "Failed to read signals from falcons: %s: %s",
              status.GetName(), status.GetDescription());
    }

    auto builder = can_position_sender_.MakeBuilder();

    for (auto falcon : {right_front_, right_back_, right_under_, left_front_,
                        left_back_, left_under_, roller_falcon_}) {
      falcon->RefreshNontimesyncedSignals();
    }

    aos::SizedArray<flatbuffers::Offset<drivetrain::CANFalcon>, kCANFalconCount>
        falcons;

    for (auto falcon : {right_front_, right_back_, right_under_, left_front_,
                        left_back_, left_under_}) {
      falcons.push_back(falcon->WritePosition(builder.fbb()));
    }

    auto falcons_list =
        builder.fbb()->CreateVector<flatbuffers::Offset<drivetrain::CANFalcon>>(
            falcons);

    drivetrain::CANPosition::Builder can_position_builder =
        builder.MakeBuilder<drivetrain::CANPosition>();

    can_position_builder.add_falcons(falcons_list);
    can_position_builder.add_timestamp(right_front_->GetTimestamp());
    can_position_builder.add_status(static_cast<int>(status));

    builder.CheckOk(builder.Send(can_position_builder.Finish()));

    {
      std::unique_lock<aos::stl_mutex> lock(roller_mutex_);
      superstructure::CANFalconT roller_falcon_data;
      roller_falcon_data.id = roller_falcon_->device_id();
      roller_falcon_data.supply_current = roller_falcon_->supply_current();
      roller_falcon_data.torque_current = -roller_falcon_->torque_current();
      roller_falcon_data.supply_voltage = roller_falcon_->supply_voltage();
      roller_falcon_data.device_temp = roller_falcon_->device_temp();
      roller_falcon_data.position = -roller_falcon_->position();
      roller_falcon_data_ =
          std::make_optional<superstructure::CANFalconT>(roller_falcon_data);
    }
  }

  aos::EventLoop *event_loop_;

  aos::SizedArray<ctre::phoenixpro::BaseStatusSignalValue *,
                  kCANFalconCount * kCANSignalsCount + kRollerSignalsCount>
      signals_;
  aos::Sender<drivetrain::CANPosition> can_position_sender_;

  std::shared_ptr<Falcon> right_front_, right_back_, right_under_, left_front_,
      left_back_, left_under_, roller_falcon_;

  std::optional<superstructure::CANFalconT> roller_falcon_data_;

  aos::stl_mutex roller_mutex_;

  // Pointer to the timer handler used to modify the wakeup.
  ::aos::TimerHandler *timer_handler_;
};

// Class to send position messages with sensor readings to our loops.
class SensorReader : public ::frc971::wpilib::SensorReader {
 public:
  SensorReader(::aos::ShmEventLoop *event_loop,
               std::shared_ptr<const Values> values,
               CANSensorReader *can_sensor_reader)
      : ::frc971::wpilib::SensorReader(event_loop),
        values_(std::move(values)),
        auto_mode_sender_(
            event_loop->MakeSender<::frc971::autonomous::AutonomousMode>(
                "/autonomous")),
        superstructure_position_sender_(
            event_loop->MakeSender<superstructure::Position>(
                "/superstructure")),
        drivetrain_position_sender_(
            event_loop
                ->MakeSender<::frc971::control_loops::drivetrain::Position>(
                    "/drivetrain")),
        gyro_sender_(event_loop->MakeSender<::frc971::sensors::GyroReading>(
            "/drivetrain")),
        can_sensor_reader_(can_sensor_reader) {
    // Set to filter out anything shorter than 1/4 of the minimum pulse width
    // we should ever see.
    UpdateFastEncoderFilterHz(kMaxFastEncoderPulsesPerSecond);
    event_loop->SetRuntimeAffinity(aos::MakeCpusetFromCpus({0}));
  }

  void Start() override {
    AddToDMA(&imu_heading_reader_);
    AddToDMA(&imu_yaw_rate_reader_);
    AddToDMA(&cone_position_sensor_);
  }

  // Auto mode switches.
  void set_autonomous_mode(int i, ::std::unique_ptr<frc::DigitalInput> sensor) {
    autonomous_modes_.at(i) = ::std::move(sensor);
  }

  void set_heading_input(::std::unique_ptr<frc::DigitalInput> sensor) {
    imu_heading_input_ = ::std::move(sensor);
    imu_heading_reader_.set_input(imu_heading_input_.get());
  }

  void set_yaw_rate_input(::std::unique_ptr<frc::DigitalInput> sensor) {
    imu_yaw_rate_input_ = ::std::move(sensor);
    imu_yaw_rate_reader_.set_input(imu_yaw_rate_input_.get());
  }

  void RunIteration() override {
    superstructure_reading_->Set(true);
    {
      auto builder = superstructure_position_sender_.MakeBuilder();
      frc971::PotAndAbsolutePositionT proximal;
      CopyPosition(proximal_encoder_, &proximal,
                   Values::kProximalEncoderCountsPerRevolution(),
                   Values::kProximalEncoderRatio(), proximal_pot_translate,
                   true, values_->arm_proximal.potentiometer_offset);
      frc971::PotAndAbsolutePositionT distal;
      CopyPosition(distal_encoder_, &distal,
                   Values::kDistalEncoderCountsPerRevolution(),
                   Values::kDistalEncoderRatio(), distal_pot_translate, true,
                   values_->arm_distal.potentiometer_offset);
      frc971::PotAndAbsolutePositionT roll_joint;
      CopyPosition(roll_joint_encoder_, &roll_joint,
                   Values::kRollJointEncoderCountsPerRevolution(),
                   Values::kRollJointEncoderRatio(), roll_joint_pot_translate,
                   true, values_->roll_joint.potentiometer_offset);
      frc971::AbsolutePositionT wrist;
      CopyPosition(wrist_encoder_, &wrist,
                   Values::kWristEncoderCountsPerRevolution(),
                   Values::kWristEncoderRatio(), false);

      flatbuffers::Offset<frc971::PotAndAbsolutePosition> proximal_offset =
          frc971::PotAndAbsolutePosition::Pack(*builder.fbb(), &proximal);
      flatbuffers::Offset<frc971::PotAndAbsolutePosition> distal_offset =
          frc971::PotAndAbsolutePosition::Pack(*builder.fbb(), &distal);
      flatbuffers::Offset<frc971::PotAndAbsolutePosition> roll_joint_offset =
          frc971::PotAndAbsolutePosition::Pack(*builder.fbb(), &roll_joint);
      flatbuffers::Offset<superstructure::ArmPosition> arm_offset =
          superstructure::CreateArmPosition(*builder.fbb(), proximal_offset,
                                            distal_offset, roll_joint_offset);
      flatbuffers::Offset<frc971::AbsolutePosition> wrist_offset =
          frc971::AbsolutePosition::Pack(*builder.fbb(), &wrist);

      flatbuffers::Offset<superstructure::CANFalcon> roller_falcon_offset;
      auto optional_roller_falcon = can_sensor_reader_->roller_falcon_data();
      if (optional_roller_falcon.has_value()) {
        roller_falcon_offset = superstructure::CANFalcon::Pack(
            *builder.fbb(), &optional_roller_falcon.value());
      }

      superstructure::Position::Builder position_builder =
          builder.MakeBuilder<superstructure::Position>();

      position_builder.add_arm(arm_offset);
      position_builder.add_wrist(wrist_offset);
      position_builder.add_end_effector_cube_beam_break(
          end_effector_cube_beam_break_->Get());
      position_builder.add_cone_position(cone_position_sensor_.last_width() /
                                         cone_position_sensor_.last_period());
      if (!roller_falcon_offset.IsNull()) {
        position_builder.add_roller_falcon(roller_falcon_offset);
      }
      builder.CheckOk(builder.Send(position_builder.Finish()));
    }

    {
      auto builder = drivetrain_position_sender_.MakeBuilder();
      frc971::control_loops::drivetrain::Position::Builder drivetrain_builder =
          builder.MakeBuilder<frc971::control_loops::drivetrain::Position>();
      drivetrain_builder.add_left_encoder(
          constants::Values::DrivetrainEncoderToMeters(
              drivetrain_left_encoder_->GetRaw()));
      drivetrain_builder.add_left_speed(
          drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod()));

      drivetrain_builder.add_right_encoder(
          -constants::Values::DrivetrainEncoderToMeters(
              drivetrain_right_encoder_->GetRaw()));
      drivetrain_builder.add_right_speed(-drivetrain_velocity_translate(
          drivetrain_right_encoder_->GetPeriod()));

      builder.CheckOk(builder.Send(drivetrain_builder.Finish()));
    }

    {
      auto builder = gyro_sender_.MakeBuilder();
      ::frc971::sensors::GyroReading::Builder gyro_reading_builder =
          builder.MakeBuilder<::frc971::sensors::GyroReading>();
      // +/- 2000 deg / sec
      constexpr double kMaxVelocity = 4000;  // degrees / second
      constexpr double kVelocityRadiansPerSecond =
          kMaxVelocity / 360 * (2.0 * M_PI);

      // Only part of the full range is used to prevent being 100% on or off.
      constexpr double kScaledRangeLow = 0.1;
      constexpr double kScaledRangeHigh = 0.9;

      constexpr double kPWMFrequencyHz = 200;
      double heading_duty_cycle =
          imu_heading_reader_.last_width() * kPWMFrequencyHz;
      double velocity_duty_cycle =
          imu_yaw_rate_reader_.last_width() * kPWMFrequencyHz;

      constexpr double kDutyCycleScale =
          1 / (kScaledRangeHigh - kScaledRangeLow);
      // scale from 0.1 - 0.9 to 0 - 1
      double rescaled_heading_duty_cycle =
          (heading_duty_cycle - kScaledRangeLow) * kDutyCycleScale;
      double rescaled_velocity_duty_cycle =
          (velocity_duty_cycle - kScaledRangeLow) * kDutyCycleScale;

      if (!std::isnan(rescaled_heading_duty_cycle)) {
        gyro_reading_builder.add_angle(rescaled_heading_duty_cycle *
                                       (2.0 * M_PI));
      }
      if (!std::isnan(rescaled_velocity_duty_cycle)) {
        gyro_reading_builder.add_velocity((rescaled_velocity_duty_cycle - 0.5) *
                                          kVelocityRadiansPerSecond);
      }
      builder.CheckOk(builder.Send(gyro_reading_builder.Finish()));
    }

    {
      auto builder = auto_mode_sender_.MakeBuilder();

      uint32_t mode = 0;
      for (size_t i = 0; i < autonomous_modes_.size(); ++i) {
        if (autonomous_modes_[i] && autonomous_modes_[i]->Get()) {
          mode |= 1 << i;
        }
      }

      auto auto_mode_builder =
          builder.MakeBuilder<frc971::autonomous::AutonomousMode>();

      auto_mode_builder.add_mode(mode);

      builder.CheckOk(builder.Send(auto_mode_builder.Finish()));
    }
  }

  std::shared_ptr<frc::DigitalOutput> superstructure_reading_;

  void set_superstructure_reading(
      std::shared_ptr<frc::DigitalOutput> superstructure_reading) {
    superstructure_reading_ = superstructure_reading;
  }

  void set_proximal_encoder(::std::unique_ptr<frc::Encoder> encoder) {
    fast_encoder_filter_.Add(encoder.get());
    proximal_encoder_.set_encoder(::std::move(encoder));
  }

  void set_proximal_absolute_pwm(
      ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
    proximal_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
  }

  void set_proximal_potentiometer(
      ::std::unique_ptr<frc::AnalogInput> potentiometer) {
    proximal_encoder_.set_potentiometer(::std::move(potentiometer));
  }

  void set_distal_encoder(::std::unique_ptr<frc::Encoder> encoder) {
    fast_encoder_filter_.Add(encoder.get());
    distal_encoder_.set_encoder(::std::move(encoder));
  }

  void set_distal_absolute_pwm(
      ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
    distal_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
  }

  void set_distal_potentiometer(
      ::std::unique_ptr<frc::AnalogInput> potentiometer) {
    distal_encoder_.set_potentiometer(::std::move(potentiometer));
  }

  void set_roll_joint_encoder(::std::unique_ptr<frc::Encoder> encoder) {
    fast_encoder_filter_.Add(encoder.get());
    roll_joint_encoder_.set_encoder(::std::move(encoder));
  }

  void set_roll_joint_absolute_pwm(
      ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
    roll_joint_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
  }

  void set_roll_joint_potentiometer(
      ::std::unique_ptr<frc::AnalogInput> potentiometer) {
    roll_joint_encoder_.set_potentiometer(::std::move(potentiometer));
  }

  void set_wrist_encoder(::std::unique_ptr<frc::Encoder> encoder) {
    fast_encoder_filter_.Add(encoder.get());
    wrist_encoder_.set_encoder(::std::move(encoder));
  }

  void set_wrist_absolute_pwm(
      ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
    wrist_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
  }

  void set_end_effector_cube_beam_break(
      ::std::unique_ptr<frc::DigitalInput> sensor) {
    end_effector_cube_beam_break_ = ::std::move(sensor);
  }

  void set_cone_position_sensor(::std::unique_ptr<frc::DigitalInput> sensor) {
    cone_position_input_ = ::std::move(sensor);
    cone_position_sensor_.set_input(cone_position_input_.get());
  }

 private:
  std::shared_ptr<const Values> values_;

  aos::Sender<frc971::autonomous::AutonomousMode> auto_mode_sender_;
  aos::Sender<superstructure::Position> superstructure_position_sender_;
  aos::Sender<frc971::control_loops::drivetrain::Position>
      drivetrain_position_sender_;
  ::aos::Sender<::frc971::sensors::GyroReading> gyro_sender_;

  std::array<std::unique_ptr<frc::DigitalInput>, 2> autonomous_modes_;

  std::unique_ptr<frc::DigitalInput> imu_heading_input_, imu_yaw_rate_input_,
      end_effector_cube_beam_break_;

  frc971::wpilib::DMAPulseWidthReader imu_heading_reader_, imu_yaw_rate_reader_;

  frc971::wpilib::AbsoluteEncoderAndPotentiometer proximal_encoder_,
      distal_encoder_, roll_joint_encoder_;
  frc971::wpilib::AbsoluteEncoder wrist_encoder_;

  frc971::wpilib::DMAPulseWidthReader cone_position_sensor_;
  std::unique_ptr<frc::DigitalInput> cone_position_input_;

  CANSensorReader *can_sensor_reader_;
};

class SuperstructureWriter
    : public ::frc971::wpilib::LoopOutputHandler<superstructure::Output> {
 public:
  SuperstructureWriter(aos::EventLoop *event_loop)
      : frc971::wpilib::LoopOutputHandler<superstructure::Output>(
            event_loop, "/superstructure") {
    event_loop->SetRuntimeRealtimePriority(
        constants::Values::kDrivetrainWriterPriority);
  }

  std::shared_ptr<frc::DigitalOutput> superstructure_reading_;

  void set_superstructure_reading(
      std::shared_ptr<frc::DigitalOutput> superstructure_reading) {
    superstructure_reading_ = superstructure_reading;
  }

  void set_proximal_falcon(::std::unique_ptr<::frc::TalonFX> t) {
    proximal_falcon_ = ::std::move(t);
  }

  void set_distal_falcon(::std::unique_ptr<::frc::TalonFX> t) {
    distal_falcon_ = ::std::move(t);
  }

  void set_roll_joint_victor(::std::unique_ptr<::frc::VictorSP> t) {
    roll_joint_victor_ = ::std::move(t);
  }

  void set_wrist_victor(::std::unique_ptr<::frc::VictorSP> t) {
    wrist_victor_ = ::std::move(t);
  }

 private:
  void Stop() override {
    AOS_LOG(WARNING, "Superstructure output too old.\n");
    proximal_falcon_->SetDisabled();
    distal_falcon_->SetDisabled();
    roll_joint_victor_->SetDisabled();
    wrist_victor_->SetDisabled();
  }

  void Write(const superstructure::Output &output) override {
    WritePwm(output.proximal_voltage(), proximal_falcon_.get());
    WritePwm(output.distal_voltage(), distal_falcon_.get());
    WritePwm(-output.roll_joint_voltage(), roll_joint_victor_.get());
    WritePwm(output.wrist_voltage(), wrist_victor_.get());
  }

  static void WriteCan(const double voltage,
                       ::ctre::phoenix::motorcontrol::can::TalonFX *falcon) {
    falcon->Set(
        ctre::phoenix::motorcontrol::ControlMode::PercentOutput,
        std::clamp(voltage, -kMaxBringupPower, kMaxBringupPower) / 12.0);
  }

  template <typename T>
  static void WritePwm(const double voltage, T *motor) {
    motor->SetSpeed(std::clamp(voltage, -kMaxBringupPower, kMaxBringupPower) /
                    12.0);
  }

  ::std::unique_ptr<::frc::TalonFX> proximal_falcon_, distal_falcon_;
  ::std::unique_ptr<::frc::VictorSP> roll_joint_victor_, wrist_victor_;
};

class SuperstructureCANWriter
    : public ::frc971::wpilib::LoopOutputHandler<superstructure::Output> {
 public:
  SuperstructureCANWriter(::aos::EventLoop *event_loop)
      : ::frc971::wpilib::LoopOutputHandler<superstructure::Output>(
            event_loop, "/superstructure") {
    event_loop->SetRuntimeRealtimePriority(
        constants::Values::kSuperstructureCANWriterPriority);

    event_loop->OnRun([this]() { WriteConfigs(); });
  };

  void set_roller_falcon(std::shared_ptr<Falcon> roller_falcon) {
    roller_falcon_ = std::move(roller_falcon);
  }

 private:
  void WriteConfigs() { roller_falcon_->WriteRollerConfigs(); }

  void Write(const superstructure::Output &output) override {
    ctre::phoenixpro::controls::DutyCycleOut roller_control(
        SafeSpeed(-output.roller_voltage()));
    roller_control.UpdateFreqHz = 0_Hz;
    roller_control.EnableFOC = true;

    ctre::phoenix::StatusCode status =
        roller_falcon_->talon()->SetControl(roller_control);

    if (!status.IsOK()) {
      AOS_LOG(ERROR, "Failed to write control to falcon: %s: %s",
              status.GetName(), status.GetDescription());
    }
  }

  void Stop() override {
    AOS_LOG(WARNING, "Superstructure CAN output too old.\n");
    ctre::phoenixpro::controls::NeutralOut stop_command;

    roller_falcon_->talon()->SetControl(stop_command);
  }

  double SafeSpeed(double voltage) {
    return (::aos::Clip(voltage, -kMaxBringupPower, kMaxBringupPower) / 12.0);
  }

  std::shared_ptr<Falcon> roller_falcon_;
};

class DrivetrainWriter : public ::frc971::wpilib::LoopOutputHandler<
                             ::frc971::control_loops::drivetrain::Output> {
 public:
  DrivetrainWriter(::aos::EventLoop *event_loop)
      : ::frc971::wpilib::LoopOutputHandler<
            ::frc971::control_loops::drivetrain::Output>(event_loop,
                                                         "/drivetrain") {
    event_loop->SetRuntimeRealtimePriority(
        constants::Values::kDrivetrainWriterPriority);

    event_loop->OnRun([this]() { WriteConfigs(); });
  }

  void set_falcons(std::shared_ptr<Falcon> right_front,
                   std::shared_ptr<Falcon> right_back,
                   std::shared_ptr<Falcon> right_under,
                   std::shared_ptr<Falcon> left_front,
                   std::shared_ptr<Falcon> left_back,
                   std::shared_ptr<Falcon> left_under) {
    right_front_ = std::move(right_front);
    right_back_ = std::move(right_back);
    right_under_ = std::move(right_under);
    left_front_ = std::move(left_front);
    left_back_ = std::move(left_back);
    left_under_ = std::move(left_under);
  }

  void set_right_inverted(ctre::phoenixpro::signals::InvertedValue invert) {
    right_inverted_ = invert;
  }

  void set_left_inverted(ctre::phoenixpro::signals::InvertedValue invert) {
    left_inverted_ = invert;
  }

 private:
  void WriteConfigs() {
    for (auto falcon :
         {right_front_.get(), right_back_.get(), right_under_.get()}) {
      falcon->WriteConfigs(right_inverted_);
    }

    for (auto falcon :
         {left_front_.get(), left_back_.get(), left_under_.get()}) {
      falcon->WriteConfigs(left_inverted_);
    }
  }

  void Write(
      const ::frc971::control_loops::drivetrain::Output &output) override {
    ctre::phoenixpro::controls::DutyCycleOut left_control(
        SafeSpeed(output.left_voltage()));
    left_control.UpdateFreqHz = 0_Hz;
    left_control.EnableFOC = true;

    ctre::phoenixpro::controls::DutyCycleOut right_control(
        SafeSpeed(output.right_voltage()));
    right_control.UpdateFreqHz = 0_Hz;
    right_control.EnableFOC = true;

    for (auto falcon :
         {left_front_.get(), left_back_.get(), left_under_.get()}) {
      ctre::phoenix::StatusCode status =
          falcon->talon()->SetControl(left_control);

      if (!status.IsOK()) {
        AOS_LOG(ERROR, "Failed to write control to falcon: %s: %s",
                status.GetName(), status.GetDescription());
      }
    }

    for (auto falcon :
         {right_front_.get(), right_back_.get(), right_under_.get()}) {
      ctre::phoenix::StatusCode status =
          falcon->talon()->SetControl(right_control);

      if (!status.IsOK()) {
        AOS_LOG(ERROR, "Failed to write control to falcon: %s: %s",
                status.GetName(), status.GetDescription());
      }
    }
  }

  void Stop() override {
    AOS_LOG(WARNING, "drivetrain output too old\n");
    ctre::phoenixpro::controls::NeutralOut stop_command;
    for (auto falcon :
         {right_front_.get(), right_back_.get(), right_under_.get(),
          left_front_.get(), left_back_.get(), left_under_.get()}) {
      falcon->talon()->SetControl(stop_command);
    }
  }

  double SafeSpeed(double voltage) {
    return (::aos::Clip(voltage, -kMaxBringupPower, kMaxBringupPower) / 12.0);
  }

  ctre::phoenixpro::signals::InvertedValue left_inverted_, right_inverted_;
  std::shared_ptr<Falcon> right_front_, right_back_, right_under_, left_front_,
      left_back_, left_under_;
};

class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
 public:
  ::std::unique_ptr<frc::Encoder> make_encoder(int index) {
    return make_unique<frc::Encoder>(10 + index * 2, 11 + index * 2, false,
                                     frc::Encoder::k4X);
  }

  void Run() override {
    std::shared_ptr<const Values> values =
        std::make_shared<const Values>(constants::MakeValues());

    aos::FlatbufferDetachedBuffer<aos::Configuration> config =
        aos::configuration::ReadConfig("aos_config.json");

    // Thread 1.
    ::aos::ShmEventLoop joystick_sender_event_loop(&config.message());
    ::frc971::wpilib::JoystickSender joystick_sender(
        &joystick_sender_event_loop);
    AddLoop(&joystick_sender_event_loop);

    // Thread 2.
    ::aos::ShmEventLoop pdp_fetcher_event_loop(&config.message());
    ::frc971::wpilib::PDPFetcher pdp_fetcher(&pdp_fetcher_event_loop);
    AddLoop(&pdp_fetcher_event_loop);

    std::shared_ptr<frc::DigitalOutput> superstructure_reading =
        make_unique<frc::DigitalOutput>(25);

    // Thread 3.
    ::aos::ShmEventLoop can_sensor_reader_event_loop(&config.message());
    can_sensor_reader_event_loop.set_name("CANSensorReader");
    CANSensorReader can_sensor_reader(&can_sensor_reader_event_loop);

    std::shared_ptr<Falcon> right_front = std::make_shared<Falcon>(
        1, "Drivetrain Bus", can_sensor_reader.get_signals_registry());
    std::shared_ptr<Falcon> right_back = std::make_shared<Falcon>(
        2, "Drivetrain Bus", can_sensor_reader.get_signals_registry());
    std::shared_ptr<Falcon> right_under = std::make_shared<Falcon>(
        3, "Drivetrain Bus", can_sensor_reader.get_signals_registry());
    std::shared_ptr<Falcon> left_front = std::make_shared<Falcon>(
        4, "Drivetrain Bus", can_sensor_reader.get_signals_registry());
    std::shared_ptr<Falcon> left_back = std::make_shared<Falcon>(
        5, "Drivetrain Bus", can_sensor_reader.get_signals_registry());
    std::shared_ptr<Falcon> left_under = std::make_shared<Falcon>(
        6, "Drivetrain Bus", can_sensor_reader.get_signals_registry());
    std::shared_ptr<Falcon> roller = std::make_shared<Falcon>(
        13, "Drivetrain Bus", can_sensor_reader.get_signals_registry());

    can_sensor_reader.set_falcons(right_front, right_back, right_under,
                                  left_front, left_back, left_under, roller);

    AddLoop(&can_sensor_reader_event_loop);

    // Thread 4.
    ::aos::ShmEventLoop sensor_reader_event_loop(&config.message());
    SensorReader sensor_reader(&sensor_reader_event_loop, values,
                               &can_sensor_reader);
    sensor_reader.set_pwm_trigger(true);
    sensor_reader.set_drivetrain_left_encoder(make_encoder(1));
    sensor_reader.set_drivetrain_right_encoder(make_encoder(0));
    sensor_reader.set_superstructure_reading(superstructure_reading);
    sensor_reader.set_heading_input(make_unique<frc::DigitalInput>(1));
    sensor_reader.set_yaw_rate_input(make_unique<frc::DigitalInput>(0));

    sensor_reader.set_proximal_encoder(make_encoder(3));
    sensor_reader.set_proximal_absolute_pwm(make_unique<frc::DigitalInput>(3));
    sensor_reader.set_proximal_potentiometer(make_unique<frc::AnalogInput>(3));

    sensor_reader.set_distal_encoder(make_encoder(2));
    sensor_reader.set_distal_absolute_pwm(make_unique<frc::DigitalInput>(2));
    sensor_reader.set_distal_potentiometer(make_unique<frc::AnalogInput>(2));

    sensor_reader.set_roll_joint_encoder(make_encoder(5));
    sensor_reader.set_roll_joint_absolute_pwm(
        make_unique<frc::DigitalInput>(5));
    sensor_reader.set_roll_joint_potentiometer(
        make_unique<frc::AnalogInput>(5));

    sensor_reader.set_wrist_encoder(make_encoder(4));
    sensor_reader.set_wrist_absolute_pwm(make_unique<frc::DigitalInput>(4));

    sensor_reader.set_end_effector_cube_beam_break(
        make_unique<frc::DigitalInput>(7));
    sensor_reader.set_cone_position_sensor(make_unique<frc::DigitalInput>(8));

    AddLoop(&sensor_reader_event_loop);

    // Thread 5.
    // Setup CAN.
    if (!FLAGS_ctre_diag_server) {
      c_Phoenix_Diagnostics_SetSecondsToStart(-1);
      c_Phoenix_Diagnostics_Dispose();
    }

    ctre::phoenix::platform::can::CANComm_SetRxSchedPriority(
        constants::Values::kDrivetrainRxPriority, true, "Drivetrain Bus");
    ctre::phoenix::platform::can::CANComm_SetTxSchedPriority(
        constants::Values::kDrivetrainTxPriority, true, "Drivetrain Bus");

    ::aos::ShmEventLoop can_output_event_loop(&config.message());
    can_output_event_loop.set_name("CANOutputWriter");
    DrivetrainWriter drivetrain_writer(&can_output_event_loop);

    drivetrain_writer.set_falcons(right_front, right_back, right_under,
                                  left_front, left_back, left_under);
    drivetrain_writer.set_right_inverted(
        ctre::phoenixpro::signals::InvertedValue::Clockwise_Positive);
    drivetrain_writer.set_left_inverted(
        ctre::phoenixpro::signals::InvertedValue::CounterClockwise_Positive);

    SuperstructureCANWriter superstructure_can_writer(&can_output_event_loop);
    superstructure_can_writer.set_roller_falcon(roller);

    AddLoop(&can_output_event_loop);

    ::aos::ShmEventLoop output_event_loop(&config.message());
    output_event_loop.set_name("PWMOutputWriter");
    SuperstructureWriter superstructure_writer(&output_event_loop);

    superstructure_writer.set_proximal_falcon(make_unique<::frc::TalonFX>(1));
    superstructure_writer.set_distal_falcon(make_unique<::frc::TalonFX>(0));

    superstructure_writer.set_roll_joint_victor(
        make_unique<::frc::VictorSP>(3));
    superstructure_writer.set_wrist_victor(make_unique<::frc::VictorSP>(2));

    superstructure_writer.set_superstructure_reading(superstructure_reading);

    AddLoop(&output_event_loop);

    RunLoops();
  }
};

}  // namespace wpilib
}  // namespace y2023

AOS_ROBOT_CLASS(::y2023::wpilib::WPILibRobot);
