#include <unistd.h>

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

#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/TalonFX.h"
#include "frc971/wpilib/ahal/VictorSP.h"
#undef ERROR

#include "ctre/phoenix6/TalonFX.hpp"
#include "gflags/gflags.h"

#include "aos/commonmath.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/network/team_number.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 "frc971/autonomous/auto_mode_generated.h"
#include "frc971/control_loops/drivetrain/drivetrain_position_generated.h"
#include "frc971/input/robot_state_generated.h"
#include "frc971/wpilib/ADIS16448.h"
#include "frc971/wpilib/ADIS16470.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 "y2020/constants.h"
#include "y2020/control_loops/superstructure/shooter/shooter_tuning_readings_generated.h"
#include "y2020/control_loops/superstructure/superstructure_output_generated.h"
#include "y2020/control_loops/superstructure/superstructure_position_static.h"

DEFINE_bool(shooter_tuning, true,
            "If true, reads from ball beambreak sensors and sends shooter "
            "tuning readings");

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

namespace y2020::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_translate(int32_t in) {
  return ((static_cast<double>(in) /
           Values::kDrivetrainEncoderCountsPerRevolution()) *
          (2.0 * M_PI)) *
         Values::kDrivetrainEncoderRatio() *
         control_loops::drivetrain::kWheelRadius;
}

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

double turret_pot_translate(double voltage) {
  return voltage * Values::kTurretPotRatio() *
         (10.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
}

constexpr double kMaxFastEncoderPulsesPerSecond =
    std::max({Values::kMaxControlPanelEncoderPulsesPerSecond(),
              Values::kMaxFinisherEncoderPulsesPerSecond(),
              Values::kMaxAcceleratorEncoderPulsesPerSecond()});
static_assert(kMaxFastEncoderPulsesPerSecond <= 1000000.0,
              "fast encoders are too fast");
constexpr double kMaxMediumEncoderPulsesPerSecond =
    std::max({Values::kMaxDrivetrainEncoderPulsesPerSecond(),
              Values::kMaxHoodEncoderPulsesPerSecond(),
              Values::kMaxIntakeEncoderPulsesPerSecond(),
              Values::kMaxTurretEncoderPulsesPerSecond()});

static_assert(kMaxMediumEncoderPulsesPerSecond <= 400000.0,
              "medium encoders are too fast");

void PrintConfigs(ctre::phoenix6::hardware::TalonFX *talon) {
  ctre::phoenix6::configs::TalonFXConfiguration configuration;
  ctre::phoenix::StatusCode status =
      talon->GetConfigurator().Refresh(configuration);
  if (!status.IsOK()) {
    AOS_LOG(ERROR, "Failed to get falcon configuration: %s: %s",
            status.GetName(), status.GetDescription());
  }
  AOS_LOG(INFO, "configuration: %s", configuration.ToString().c_str());
}

void WriteConfigs(ctre::phoenix6::hardware::TalonFX *talon,
                  double stator_current_limit, double supply_current_limit) {
  ctre::phoenix6::configs::CurrentLimitsConfigs current_limits;
  current_limits.StatorCurrentLimit = stator_current_limit;
  current_limits.StatorCurrentLimitEnable = true;
  current_limits.SupplyCurrentLimit = supply_current_limit;
  current_limits.SupplyCurrentLimitEnable = true;

  ctre::phoenix6::configs::TalonFXConfiguration configuration;
  configuration.CurrentLimits = current_limits;

  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());
  }

  PrintConfigs(talon);
}

void Disable(ctre::phoenix6::hardware::TalonFX *talon) {
  ctre::phoenix6::controls::DutyCycleOut stop_command(0.0);
  stop_command.UpdateFreqHz = 0_Hz;
  stop_command.EnableFOC = true;

  talon->SetControl(stop_command);
}

}  // namespace

// Class to send position messages with sensor readings to our loops.
class SensorReader : public ::frc971::wpilib::SensorReader {
 public:
  SensorReader(::aos::ShmEventLoop *event_loop)
      : ::frc971::wpilib::SensorReader(event_loop),
        auto_mode_sender_(
            event_loop->MakeSender<::frc971::autonomous::AutonomousMode>(
                "/autonomous")),
        superstructure_position_sender_(
            event_loop->MakeSender<superstructure::PositionStatic>(
                "/superstructure")),
        drivetrain_position_sender_(
            event_loop
                ->MakeSender<::frc971::control_loops::drivetrain::Position>(
                    "/drivetrain")),
        shooter_tuning_readings_sender_(
            event_loop->MakeSender<superstructure::shooter::TuningReadings>(
                "/superstructure")) {
    // Set to filter out anything shorter than 1/4 of the minimum pulse width
    // we should ever see.
    UpdateFastEncoderFilterHz(kMaxFastEncoderPulsesPerSecond);
    UpdateMediumEncoderFilterHz(kMaxMediumEncoderPulsesPerSecond);

    constants::InitValues();
  }

  // Hood
  void set_hood_encoder(::std::unique_ptr<frc::Encoder> encoder) {
    medium_encoder_filter_.Add(encoder.get());
    hood_encoder_.set_encoder(::std::move(encoder));
  }

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

  void set_hood_single_turn_absolute_pwm(
      ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
    hood_encoder_.set_single_turn_absolute_pwm(::std::move(absolute_pwm));
  }

  // Intake

  void set_intake_encoder(::std::unique_ptr<frc::Encoder> encoder) {
    medium_encoder_filter_.Add(encoder.get());
    intake_joint_encoder_.set_encoder(::std::move(encoder));
  }

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

  // Turret

  void set_turret_encoder(::std::unique_ptr<frc::Encoder> encoder) {
    medium_encoder_filter_.Add(encoder.get());
    turret_encoder_.set_encoder(::std::move(encoder));
  }

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

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

  // Shooter
  void set_finisher_encoder(::std::unique_ptr<frc::Encoder> encoder) {
    fast_encoder_filter_.Add(encoder.get());
    finisher_encoder_ = ::std::move(encoder);
  }
  void set_left_accelerator_encoder(::std::unique_ptr<frc::Encoder> encoder) {
    fast_encoder_filter_.Add(encoder.get());
    left_accelerator_encoder_ = ::std::move(encoder);
  }

  void set_right_accelerator_encoder(::std::unique_ptr<frc::Encoder> encoder) {
    fast_encoder_filter_.Add(encoder.get());
    right_accelerator_encoder_ = ::std::move(encoder);
  }

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

  void set_imu(frc971::wpilib::ADIS16470 *imu) { imu_ = imu; }

  void set_ball_beambreak_inputs(::std::unique_ptr<frc::DigitalInput> sensor1,
                                 ::std::unique_ptr<frc::DigitalInput> sensor2) {
    ball_beambreak_inputs_[0] = ::std::move(sensor1);
    ball_beambreak_inputs_[1] = ::std::move(sensor2);
    ball_beambreak_reader_.set_input_one(ball_beambreak_inputs_[0].get());
    ball_beambreak_reader_.set_input_two(ball_beambreak_inputs_[1].get());
  }

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

  void Start() override {
    if (FLAGS_shooter_tuning) {
      AddToDMA(&ball_beambreak_reader_);
    }
  }

  void RunIteration() override {
    if (imu_ != nullptr) {
      imu_->DoReads();
    }

    {
      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(
          drivetrain_translate(drivetrain_left_encoder_->GetRaw()));
      drivetrain_builder.add_left_speed(
          drivetrain_velocity_translate(drivetrain_left_encoder_->GetPeriod()));

      drivetrain_builder.add_right_encoder(
          -drivetrain_translate(drivetrain_right_encoder_->GetRaw()));
      drivetrain_builder.add_right_speed(-drivetrain_velocity_translate(
          drivetrain_right_encoder_->GetPeriod()));

      builder.CheckOk(builder.Send(drivetrain_builder.Finish()));
    }
    const constants::Values &values = constants::GetValues();

    {
      aos::Sender<superstructure::PositionStatic>::StaticBuilder builder =
          superstructure_position_sender_.MakeStaticBuilder();

      // TODO(alex): check new absolute encoder api.
      // Hood
      CopyPosition(hood_encoder_, builder->add_hood(),
                   Values::kHoodEncoderCountsPerRevolution(),
                   Values::kHoodEncoderRatio(),
                   Values::kHoodSingleTurnEncoderRatio(), false);
      // Intake
      CopyPosition(intake_joint_encoder_, builder->add_intake_joint(),
                   Values::kIntakeEncoderCountsPerRevolution(),
                   Values::kIntakeEncoderRatio(), false);
      // Turret
      CopyPosition(turret_encoder_, builder->add_turret(),
                   Values::kTurretEncoderCountsPerRevolution(),
                   Values::kTurretEncoderRatio(), turret_pot_translate, true,
                   values.turret.potentiometer_offset);
      // Shooter
      y2020::control_loops::superstructure::ShooterPositionStatic *shooter =
          builder->add_shooter();
      shooter->set_theta_finisher(
          encoder_translate(-finisher_encoder_->GetRaw(),
                            Values::kFinisherEncoderCountsPerRevolution(),
                            Values::kFinisherEncoderRatio()));

      shooter->set_theta_accelerator_left(
          encoder_translate(-left_accelerator_encoder_->GetRaw(),
                            Values::kAcceleratorEncoderCountsPerRevolution(),
                            Values::kAcceleratorEncoderRatio()));
      shooter->set_theta_accelerator_right(
          encoder_translate(right_accelerator_encoder_->GetRaw(),
                            Values::kAcceleratorEncoderCountsPerRevolution(),
                            Values::kAcceleratorEncoderRatio()));
      builder->set_intake_beambreak_triggered(ball_intake_beambreak_->Get());

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

    {
      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()));
    }

    if (FLAGS_shooter_tuning) {
      // Distance between beambreak sensors, in meters.
      constexpr double kDistanceBetweenBeambreaks = 0.4813;

      if (ball_beambreak_reader_.pulses_detected() > balls_detected_) {
        balls_detected_ = ball_beambreak_reader_.pulses_detected();

        auto builder = shooter_tuning_readings_sender_.MakeBuilder();
        auto shooter_tuning_readings_builder =
            builder.MakeBuilder<superstructure::shooter::TuningReadings>();
        shooter_tuning_readings_builder.add_velocity_ball(
            kDistanceBetweenBeambreaks / ball_beambreak_reader_.last_width());
        builder.CheckOk(builder.Send(shooter_tuning_readings_builder.Finish()));
      }
    }
  }

 private:
  ::aos::Sender<::frc971::autonomous::AutonomousMode> auto_mode_sender_;
  ::aos::Sender<superstructure::PositionStatic> superstructure_position_sender_;
  ::aos::Sender<::frc971::control_loops::drivetrain::Position>
      drivetrain_position_sender_;
  ::aos::Sender<superstructure::shooter::TuningReadings>
      shooter_tuning_readings_sender_;

  ::frc971::wpilib::AbsoluteEncoderAndPotentiometer turret_encoder_;

  ::frc971::wpilib::AbsoluteAndAbsoluteEncoder hood_encoder_;

  ::frc971::wpilib::AbsoluteEncoder intake_joint_encoder_;

  ::std::unique_ptr<::frc::Encoder> finisher_encoder_,
      left_accelerator_encoder_, right_accelerator_encoder_;

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

  frc971::wpilib::ADIS16470 *imu_ = nullptr;

  std::unique_ptr<frc::DigitalInput> ball_intake_beambreak_;

  // Used to interface with the two beam break sensors that the ball for tuning
  // shooter parameters has to pass through.
  // We will time how long it takes to pass between the two sensors to get its
  // velocity.
  std::array<std::unique_ptr<frc::DigitalInput>, 2> ball_beambreak_inputs_;
  frc971::wpilib::DMAPulseSeparationReader ball_beambreak_reader_;
  int balls_detected_ = 0;
};

class SuperstructureWriter
    : public ::frc971::wpilib::LoopOutputHandler<superstructure::Output> {
 public:
  SuperstructureWriter(::aos::EventLoop *event_loop)
      : ::frc971::wpilib::LoopOutputHandler<superstructure::Output>(
            event_loop, "/superstructure") {}

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

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

  void set_intake_roller_falcon(
      ::std::unique_ptr<::ctre::phoenix6::hardware::TalonFX> t) {
    intake_roller_falcon_ = ::std::move(t);

    WriteConfigs(intake_roller_falcon_.get(),
                 Values::kIntakeRollerStatorCurrentLimit(),
                 Values::kIntakeRollerSupplyCurrentLimit());
  }

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

  void set_feeder_falcon(
      ::std::unique_ptr<::ctre::phoenix6::hardware::TalonFX> t) {
    feeder_falcon_ = ::std::move(t);

    WriteConfigs(feeder_falcon_.get(), Values::kFeederStatorCurrentLimit(),
                 Values::kFeederSupplyCurrentLimit());
  }

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

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

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

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

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

  void set_climber_falcon(
      ::std::unique_ptr<::ctre::phoenix6::hardware::TalonFX> t) {
    climber_falcon_ = ::std::move(t);
    ctre::phoenix6::configs::CurrentLimitsConfigs current_limits;
    current_limits.SupplyCurrentLimit = Values::kClimberSupplyCurrentLimit();
    current_limits.SupplyCurrentLimitEnable = true;

    ctre::phoenix6::configs::TalonFXConfiguration configuration;
    configuration.CurrentLimits = current_limits;

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

    PrintConfigs(climber_falcon_.get());
  }

 private:
  void Write(const superstructure::Output &output) override {
    hood_victor_->SetSpeed(std::clamp(-output.hood_voltage(), -kMaxBringupPower,
                                      kMaxBringupPower) /
                           12.0);

    intake_joint_victor_->SetSpeed(std::clamp(-output.intake_joint_voltage(),
                                              -kMaxBringupPower,
                                              kMaxBringupPower) /
                                   12.0);

    WriteCan(-output.intake_roller_voltage(), intake_roller_falcon_.get());

    turret_victor_->SetSpeed(std::clamp(output.turret_voltage(),
                                        -kMaxBringupPower, kMaxBringupPower) /
                             12.0);
    WriteCan(output.feeder_voltage(), feeder_falcon_.get());
    if (washing_machine_control_panel_victor_) {
      washing_machine_control_panel_victor_->SetSpeed(
          std::clamp(-output.washing_machine_spinner_voltage(),
                     -kMaxBringupPower, kMaxBringupPower) /
          12.0);
    }

    accelerator_left_falcon_->SetSpeed(
        std::clamp(-output.accelerator_left_voltage(), -kMaxBringupPower,
                   kMaxBringupPower) /
        12.0);

    accelerator_right_falcon_->SetSpeed(
        std::clamp(output.accelerator_right_voltage(), -kMaxBringupPower,
                   kMaxBringupPower) /
        12.0);

    finisher_falcon1_->SetSpeed(std::clamp(output.finisher_voltage(),
                                           -kMaxBringupPower,
                                           kMaxBringupPower) /
                                12.0);
    finisher_falcon0_->SetSpeed(std::clamp(-output.finisher_voltage(),
                                           -kMaxBringupPower,
                                           kMaxBringupPower) /
                                12.0);

    if (climber_falcon_) {
      WriteCan(output.climber_voltage(), climber_falcon_.get());
    }
  }

  static void WriteCan(const double voltage,
                       ::ctre::phoenix6::hardware::TalonFX *falcon) {
    ctre::phoenix6::controls::DutyCycleOut control(
        std::clamp(voltage, -kMaxBringupPower, kMaxBringupPower) / 12.0);
    control.UpdateFreqHz = 0_Hz;
    control.EnableFOC = true;

    falcon->SetControl(control);
  }

  void Stop() override {
    AOS_LOG(WARNING, "Superstructure output too old.\n");
    hood_victor_->SetDisabled();
    intake_joint_victor_->SetDisabled();
    turret_victor_->SetDisabled();
    if (washing_machine_control_panel_victor_) {
      washing_machine_control_panel_victor_->SetDisabled();
    }
    accelerator_left_falcon_->SetDisabled();
    accelerator_right_falcon_->SetDisabled();
    finisher_falcon0_->SetDisabled();
    finisher_falcon1_->SetDisabled();
    Disable(feeder_falcon_.get());
    Disable(intake_roller_falcon_.get());
    Disable(climber_falcon_.get());
  }

  ::std::unique_ptr<::frc::VictorSP> hood_victor_, intake_joint_victor_,
      turret_victor_, washing_machine_control_panel_victor_;

  ::std::unique_ptr<::frc::TalonFX> accelerator_left_falcon_,
      accelerator_right_falcon_, finisher_falcon0_, finisher_falcon1_;

  ::std::unique_ptr<::ctre::phoenix6::hardware::TalonFX> intake_roller_falcon_,
      climber_falcon_, feeder_falcon_;
};

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

  void Run() override {
    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);

    // Thread 3.
    ::aos::ShmEventLoop sensor_reader_event_loop(&config.message());
    SensorReader sensor_reader(&sensor_reader_event_loop);
    sensor_reader.set_pwm_trigger(true);
    sensor_reader.set_drivetrain_left_encoder(make_encoder(0));
    sensor_reader.set_drivetrain_right_encoder(make_encoder(1));
    // TODO: pin numbers
    sensor_reader.set_hood_encoder(
        make_unique<frc::Encoder>(22, 23, false, frc::Encoder::k4X));

    sensor_reader.set_hood_absolute_pwm(make_unique<frc::DigitalInput>(25));
    sensor_reader.set_hood_single_turn_absolute_pwm(
        make_unique<frc::DigitalInput>(24));

    sensor_reader.set_intake_encoder(make_encoder(5));
    sensor_reader.set_intake_absolute_pwm(make_unique<frc::DigitalInput>(1));

    sensor_reader.set_turret_encoder(make_encoder(2));
    sensor_reader.set_turret_absolute_pwm(make_unique<frc::DigitalInput>(0));
    sensor_reader.set_turret_potentiometer(make_unique<frc::AnalogInput>(0));

    sensor_reader.set_finisher_encoder(
        make_unique<frc::Encoder>(3, 2, false, frc::Encoder::k4X));
    sensor_reader.set_left_accelerator_encoder(make_encoder(4));
    sensor_reader.set_right_accelerator_encoder(make_encoder(3));

    sensor_reader.set_ball_intake_beambreak(make_unique<frc::DigitalInput>(4));

    if (FLAGS_shooter_tuning) {
      sensor_reader.set_ball_beambreak_inputs(
          make_unique<frc::DigitalInput>(6), make_unique<frc::DigitalInput>(7));
    }

    AddLoop(&sensor_reader_event_loop);

    // Note: If ADIS16470 is plugged in directly to the roboRIO SPI port without
    // the Spartan Board, then trigger is on 26, reset 27, and chip select is
    // CS0.
    // TODO(james): Double check whether the above is still accurate/useful with
    // the ADIS16448. No reason it shouldn't be.
    frc::SPI::Port spi_port = frc::SPI::Port::kOnboardCS1;
    std::unique_ptr<frc::DigitalInput> imu_trigger;
    std::unique_ptr<frc::DigitalOutput> imu_reset;
    if (::aos::network::GetTeamNumber() ==
        constants::Values::kCodingRobotTeamNumber) {
      imu_trigger = make_unique<frc::DigitalInput>(26);
      imu_reset = make_unique<frc::DigitalOutput>(27);
      spi_port = frc::SPI::Port::kOnboardCS0;
    } else {
      imu_trigger = make_unique<frc::DigitalInput>(9);
      imu_reset = make_unique<frc::DigitalOutput>(8);
    }
    ::aos::ShmEventLoop imu_event_loop(&config.message());
    std::unique_ptr<frc971::wpilib::ADIS16448> old_imu;
    std::unique_ptr<frc971::wpilib::ADIS16470> new_imu;
    std::unique_ptr<frc::SPI> imu_spi;
    if (::aos::network::GetTeamNumber() !=
        constants::Values::kCodingRobotTeamNumber) {
      old_imu = make_unique<frc971::wpilib::ADIS16448>(
          &imu_event_loop, spi_port, imu_trigger.get());
      old_imu->SetDummySPI(frc::SPI::Port::kOnboardCS2);
      old_imu->set_reset(imu_reset.get());
    } else {
      imu_spi = make_unique<frc::SPI>(spi_port);
      new_imu = make_unique<frc971::wpilib::ADIS16470>(
          &imu_event_loop, imu_spi.get(), imu_trigger.get(), imu_reset.get());
      sensor_reader.set_imu(new_imu.get());
    }
    AddLoop(&imu_event_loop);

    // Thread 4.
    ::aos::ShmEventLoop output_event_loop(&config.message());
    output_event_loop.set_name("output_writer");
    ::frc971::wpilib::DrivetrainWriter drivetrain_writer(&output_event_loop);
    drivetrain_writer.set_left_controller0(
        ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(0)), true);
    drivetrain_writer.set_right_controller0(
        ::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(1)), false);

    SuperstructureWriter superstructure_writer(&output_event_loop);
    superstructure_writer.set_hood_victor(make_unique<frc::VictorSP>(8));
    superstructure_writer.set_intake_joint_victor(
        make_unique<frc::VictorSP>(2));
    superstructure_writer.set_intake_roller_falcon(
        make_unique<::ctre::phoenix6::hardware::TalonFX>(0));
    superstructure_writer.set_turret_victor(make_unique<frc::VictorSP>(7));
    superstructure_writer.set_feeder_falcon(
        make_unique<ctre::phoenix6::hardware::TalonFX>(1));
    superstructure_writer.set_washing_machine_control_panel_victor(
        make_unique<frc::VictorSP>(6));
    superstructure_writer.set_accelerator_left_falcon(
        make_unique<::frc::TalonFX>(5));
    superstructure_writer.set_accelerator_right_falcon(
        make_unique<::frc::TalonFX>(4));
    superstructure_writer.set_finisher_falcon0(make_unique<::frc::TalonFX>(9));
    superstructure_writer.set_finisher_falcon1(make_unique<::frc::TalonFX>(3));
    // TODO: check port
    superstructure_writer.set_climber_falcon(
        make_unique<::ctre::phoenix6::hardware::TalonFX>(2));

    AddLoop(&output_event_loop);

    RunLoops();
  }
};

}  // namespace y2020::wpilib

AOS_ROBOT_CLASS(::y2020::wpilib::WPILibRobot);
