#include "frc971/zeroing/zeroing.h"

#include <algorithm>
#include <cmath>
#include <limits>
#include <vector>

#include "frc971/zeroing/wrap.h"

namespace frc971 {
namespace zeroing {
namespace {

bool compare_encoder(const PotAndAbsolutePosition &left,
                     const PotAndAbsolutePosition &right) {
  return left.encoder < right.encoder;
}

}  // namespace

PotAndIndexPulseZeroingEstimator::PotAndIndexPulseZeroingEstimator(
    const constants::PotAndIndexPulseZeroingConstants &constants)
    : constants_(constants) {
  start_pos_samples_.reserve(constants_.average_filter_size);
  Reset();
}

void PotAndIndexPulseZeroingEstimator::Reset() {
  samples_idx_ = 0;
  offset_ = 0;
  start_pos_samples_.clear();
  zeroed_ = false;
  wait_for_index_pulse_ = true;
  last_used_index_pulse_count_ = 0;
  error_ = false;
}

void PotAndIndexPulseZeroingEstimator::TriggerError() {
  if (!error_) {
    LOG(ERROR, "Manually triggered zeroing error.\n");
    error_ = true;
  }
}

double PotAndIndexPulseZeroingEstimator::CalculateStartPosition(
    double start_average, double latched_encoder) const {
  // We calculate an aproximation of the value of the last index position.
  // Also account for index pulses not lining up with integer multiples of the
  // index_diff.
  double index_pos =
      start_average + latched_encoder - constants_.measured_index_position;
  // We round index_pos to the closest valid value of the index.
  double accurate_index_pos = (round(index_pos / constants_.index_difference)) *
                              constants_.index_difference;
  // Now we reverse the first calculation to get the accurate start position.
  return accurate_index_pos - latched_encoder +
         constants_.measured_index_position;
}

void PotAndIndexPulseZeroingEstimator::UpdateEstimate(
    const PotAndIndexPosition &info) {
  // We want to make sure that we encounter at least one index pulse while
  // zeroing. So we take the index pulse count from the first sample after
  // reset and wait for that count to change before we consider ourselves
  // zeroed.
  if (wait_for_index_pulse_) {
    last_used_index_pulse_count_ = info.index_pulses;
    wait_for_index_pulse_ = false;
  }

  if (start_pos_samples_.size() < constants_.average_filter_size) {
    start_pos_samples_.push_back(info.pot - info.encoder);
  } else {
    start_pos_samples_[samples_idx_] = info.pot - info.encoder;
  }

  // Drop the oldest sample when we run this function the next time around.
  samples_idx_ = (samples_idx_ + 1) % constants_.average_filter_size;

  double sample_sum = 0.0;

  for (size_t i = 0; i < start_pos_samples_.size(); ++i) {
    sample_sum += start_pos_samples_[i];
  }

  // Calculates the average of the starting position.
  double start_average = sample_sum / start_pos_samples_.size();

  // If there are no index pulses to use or we don't have enough samples yet to
  // have a well-filtered starting position then we use the filtered value as
  // our best guess.
  if (!zeroed_ &&
      (info.index_pulses == last_used_index_pulse_count_ || !offset_ready())) {
    offset_ = start_average;
  } else if (!zeroed_ || last_used_index_pulse_count_ != info.index_pulses) {
    // Note the accurate start position and the current index pulse count so
    // that we only run this logic once per index pulse. That should be more
    // resilient to corrupted intermediate data.
    offset_ = CalculateStartPosition(start_average, info.latched_encoder);
    last_used_index_pulse_count_ = info.index_pulses;

    // TODO(austin): Reject encoder positions which have x% error rather than
    // rounding to the closest index pulse.

    // Save the first starting position.
    if (!zeroed_) {
      first_start_pos_ = offset_;
      LOG(INFO, "latching start position %f\n", first_start_pos_);
    }

    // Now that we have an accurate starting position we can consider ourselves
    // zeroed.
    zeroed_ = true;
    // Throw an error if first_start_pos is bigger/smaller than
    // constants_.allowable_encoder_error * index_diff + start_pos.
    if (::std::abs(first_start_pos_ - offset_) >
        constants_.allowable_encoder_error * constants_.index_difference) {
      if (!error_) {
        LOG(ERROR,
            "Encoder ticks out of range since last index pulse. first start "
            "position: %f recent starting position: %f, allowable error: %f\n",
            first_start_pos_, offset_,
            constants_.allowable_encoder_error * constants_.index_difference);
        error_ = true;
      }
    }
  }

  position_ = offset_ + info.encoder;
  filtered_position_ = start_average + info.encoder;
}

PotAndIndexPulseZeroingEstimator::State
PotAndIndexPulseZeroingEstimator::GetEstimatorState() const {
  State r;
  r.error = error_;
  r.zeroed = zeroed_;
  r.position = position_;
  r.pot_position = filtered_position_;
  return r;
}

HallEffectAndPositionZeroingEstimator::HallEffectAndPositionZeroingEstimator(
    const ZeroingConstants &constants)
    : constants_(constants) {
  Reset();
}

void HallEffectAndPositionZeroingEstimator::Reset() {
  offset_ = 0.0;
  min_low_position_ = ::std::numeric_limits<double>::max();
  max_low_position_ = ::std::numeric_limits<double>::lowest();
  zeroed_ = false;
  initialized_ = false;
  last_used_posedge_count_ = 0;
  cycles_high_ = 0;
  high_long_enough_ = false;
  first_start_pos_ = 0.0;
  error_ = false;
  current_ = 0.0;
  first_start_pos_ = 0.0;
}

void HallEffectAndPositionZeroingEstimator::TriggerError() {
  if (!error_) {
    LOG(ERROR, "Manually triggered zeroing error.\n");
    error_ = true;
  }
}

void HallEffectAndPositionZeroingEstimator::StoreEncoderMaxAndMin(
    const HallEffectAndPosition &info) {
  // If we have a new posedge.
  if (!info.current) {
    if (last_hall_) {
      min_low_position_ = max_low_position_ = info.position;
    } else {
      min_low_position_ = ::std::min(min_low_position_, info.position);
      max_low_position_ = ::std::max(max_low_position_, info.position);
    }
  }
  last_hall_ = info.current;
}

void HallEffectAndPositionZeroingEstimator::UpdateEstimate(
    const HallEffectAndPosition &info) {
  // We want to make sure that we encounter at least one posedge while zeroing.
  // So we take the posedge count from the first sample after reset and wait for
  // that count to change and for the hall effect to stay high before we
  // consider ourselves zeroed.
  if (!initialized_) {
    last_used_posedge_count_ = info.posedge_count;
    initialized_ = true;
    last_hall_ = info.current;
  }

  StoreEncoderMaxAndMin(info);

  if (info.current) {
    cycles_high_++;
  } else {
    cycles_high_ = 0;
    last_used_posedge_count_ = info.posedge_count;
  }

  high_long_enough_ = cycles_high_ >= constants_.hall_trigger_zeroing_length;

  bool moving_backward = false;
  if (constants_.zeroing_move_direction) {
    moving_backward = info.position > min_low_position_;
  } else {
    moving_backward = info.position < max_low_position_;
  }

  // If there are no posedges to use or we don't have enough samples yet to
  // have a well-filtered starting position then we use the filtered value as
  // our best guess.
  if (last_used_posedge_count_ != info.posedge_count && high_long_enough_ &&
      moving_backward) {
    // Note the offset and the current posedge count so that we only run this
    // logic once per posedge. That should be more resilient to corrupted
    // intermediate data.
    offset_ = -info.posedge_value;
    if (constants_.zeroing_move_direction) {
      offset_ += constants_.lower_hall_position;
    } else {
      offset_ += constants_.upper_hall_position;
    }
    last_used_posedge_count_ = info.posedge_count;

    // Save the first starting position.
    if (!zeroed_) {
      first_start_pos_ = offset_;
      LOG(INFO, "latching start position %f\n", first_start_pos_);
    }

    // Now that we have an accurate starting position we can consider ourselves
    // zeroed.
    zeroed_ = true;
  }

  position_ = info.position - offset_;
}

HallEffectAndPositionZeroingEstimator::State
HallEffectAndPositionZeroingEstimator::GetEstimatorState() const {
  State r;
  r.error = error_;
  r.zeroed = zeroed_;
  r.encoder = position_;
  r.high_long_enough = high_long_enough_;
  r.offset = offset_;
  return r;
}

PotAndAbsEncoderZeroingEstimator::PotAndAbsEncoderZeroingEstimator(
    const constants::PotAndAbsoluteEncoderZeroingConstants &constants)
    : constants_(constants) {
  relative_to_absolute_offset_samples_.reserve(constants_.average_filter_size);
  offset_samples_.reserve(constants_.average_filter_size);
  Reset();
}

void PotAndAbsEncoderZeroingEstimator::Reset() {
  first_offset_ = 0.0;
  pot_relative_encoder_offset_ = 0.0;
  offset_ = 0.0;
  samples_idx_ = 0;
  filtered_position_ = 0.0;
  position_ = 0.0;
  zeroed_ = false;
  nan_samples_ = 0;
  relative_to_absolute_offset_samples_.clear();
  offset_samples_.clear();
  buffered_samples_.clear();
  error_ = false;
}

// So, this needs to be a multistep process.  We need to first estimate the
// offset between the absolute encoder and the relative encoder.  That process
// should get us an absolute number which is off by integer multiples of the
// distance/rev.  In parallel, we can estimate the offset between the pot and
// encoder.  When both estimates have converged, we can then compute the offset
// in a cycle, and which cycle, which gives us the accurate global offset.
//
// It's tricky to compute the offset between the absolute and relative encoder.
// We need to compute this inside 1 revolution.  The easiest way to do this
// would be to wrap the encoder, subtract the two of them, and then average the
// result.  That will struggle when they are off by PI.  Instead, we need to
// wrap the number to +- PI from the current averaged offset.
//
// To guard against the robot moving while updating estimates, buffer a number
// of samples and check that the buffered samples are not different than the
// zeroing threshold. At any point that the samples differ too much, do not
// update estimates based on those samples.
void PotAndAbsEncoderZeroingEstimator::UpdateEstimate(
    const PotAndAbsolutePosition &info) {
  // Check for Abs Encoder NaN value that would mess up the rest of the zeroing
  // code below. NaN values are given when the Absolute Encoder is disconnected.
  if (::std::isnan(info.absolute_encoder)) {
    if (zeroed_) {
      LOG(ERROR, "NAN on absolute encoder\n");
      error_ = true;
    } else {
      ++nan_samples_;
      LOG(ERROR, "NAN on absolute encoder while zeroing %d\n",
          static_cast<int>(nan_samples_));
      if (nan_samples_ >= constants_.average_filter_size) {
        error_ = true;
        zeroed_ = true;
      }
    }
    // Throw some dummy values in for now.
    filtered_absolute_encoder_ = info.absolute_encoder;
    filtered_position_ = pot_relative_encoder_offset_ + info.encoder;
    position_ = offset_ + info.encoder;
    return;
  }

  bool moving = true;
  if (buffered_samples_.size() < constants_.moving_buffer_size) {
    // Not enough samples to start determining if the robot is moving or not,
    // don't use the samples yet.
    buffered_samples_.push_back(info);
  } else {
    // Have enough samples to start determining if the robot is moving or not.
    buffered_samples_[buffered_samples_idx_] = info;
    auto max_value =
        ::std::max_element(buffered_samples_.begin(), buffered_samples_.end(),
                           compare_encoder)->encoder;
    auto min_value =
        ::std::min_element(buffered_samples_.begin(), buffered_samples_.end(),
                           compare_encoder)->encoder;
    if (::std::abs(max_value - min_value) < constants_.zeroing_threshold) {
      // Robot isn't moving, use middle sample to determine offsets.
      moving = false;
    }
  }
  buffered_samples_idx_ =
      (buffered_samples_idx_ + 1) % constants_.moving_buffer_size;

  if (!moving) {
    // The robot is not moving, use the middle sample to determine offsets.
    const int middle_index =
        (buffered_samples_idx_ + (constants_.moving_buffer_size - 1) / 2) %
        constants_.moving_buffer_size;

    // Compute the sum of all the offset samples.
    double relative_to_absolute_offset_sum = 0.0;
    for (size_t i = 0; i < relative_to_absolute_offset_samples_.size(); ++i) {
      relative_to_absolute_offset_sum +=
          relative_to_absolute_offset_samples_[i];
    }

    // Compute the average offset between the absolute encoder and relative
    // encoder.  If we have 0 samples, assume it is 0.
    double average_relative_to_absolute_offset =
        relative_to_absolute_offset_samples_.size() == 0
            ? 0.0
            : relative_to_absolute_offset_sum /
                  relative_to_absolute_offset_samples_.size();

    const double adjusted_incremental_encoder =
        buffered_samples_[middle_index].encoder +
        average_relative_to_absolute_offset;

    // Now, compute the nearest absolute encoder value to the offset relative
    // encoder position.
    const double adjusted_absolute_encoder =
        Wrap(adjusted_incremental_encoder,
             buffered_samples_[middle_index].absolute_encoder -
                 constants_.measured_absolute_position,
             constants_.one_revolution_distance);

    // Reverse the math on the previous line to compute the absolute encoder.
    // Do this by taking the adjusted encoder, and then subtracting off the
    // second argument above, and the value that was added by Wrap.
    filtered_absolute_encoder_ =
        ((buffered_samples_[middle_index].encoder +
          average_relative_to_absolute_offset) -
         (-constants_.measured_absolute_position +
          (adjusted_absolute_encoder -
           (buffered_samples_[middle_index].absolute_encoder -
            constants_.measured_absolute_position))));

    const double relative_to_absolute_offset =
        adjusted_absolute_encoder - buffered_samples_[middle_index].encoder;

    // Add the sample and update the average with the new reading.
    const size_t relative_to_absolute_offset_samples_size =
        relative_to_absolute_offset_samples_.size();
    if (relative_to_absolute_offset_samples_size <
        constants_.average_filter_size) {
      average_relative_to_absolute_offset =
          (average_relative_to_absolute_offset *
               relative_to_absolute_offset_samples_size +
           relative_to_absolute_offset) /
          (relative_to_absolute_offset_samples_size + 1);

      relative_to_absolute_offset_samples_.push_back(
          relative_to_absolute_offset);
    } else {
      average_relative_to_absolute_offset -=
          relative_to_absolute_offset_samples_[samples_idx_] /
          relative_to_absolute_offset_samples_size;
      relative_to_absolute_offset_samples_[samples_idx_] =
          relative_to_absolute_offset;
      average_relative_to_absolute_offset +=
          relative_to_absolute_offset /
          relative_to_absolute_offset_samples_size;
    }

    // Now compute the offset between the pot and relative encoder.
    if (offset_samples_.size() < constants_.average_filter_size) {
      offset_samples_.push_back(buffered_samples_[middle_index].pot -
                                buffered_samples_[middle_index].encoder);
    } else {
      offset_samples_[samples_idx_] = buffered_samples_[middle_index].pot -
                                      buffered_samples_[middle_index].encoder;
    }

    // Drop the oldest sample when we run this function the next time around.
    samples_idx_ = (samples_idx_ + 1) % constants_.average_filter_size;

    double pot_relative_encoder_offset_sum = 0.0;
    for (size_t i = 0; i < offset_samples_.size(); ++i) {
      pot_relative_encoder_offset_sum += offset_samples_[i];
    }
    pot_relative_encoder_offset_ =
        pot_relative_encoder_offset_sum / offset_samples_.size();

    offset_ = Wrap(buffered_samples_[middle_index].encoder +
                       pot_relative_encoder_offset_,
                   average_relative_to_absolute_offset +
                       buffered_samples_[middle_index].encoder,
                   constants_.one_revolution_distance) -
              buffered_samples_[middle_index].encoder;
    if (offset_ready()) {
      if (!zeroed_) {
        first_offset_ = offset_;
      }

      if (::std::abs(first_offset_ - offset_) >
          constants_.allowable_encoder_error *
              constants_.one_revolution_distance) {
        LOG(ERROR,
            "Offset moved too far. Initial: %f, current %f, allowable change: "
            "%f\n",
            first_offset_, offset_, constants_.allowable_encoder_error *
                                        constants_.one_revolution_distance);
        error_ = true;
      }

      zeroed_ = true;
    }
  }

  // Update the position.
  filtered_position_ = pot_relative_encoder_offset_ + info.encoder;
  position_ = offset_ + info.encoder;
}

PotAndAbsEncoderZeroingEstimator::State
PotAndAbsEncoderZeroingEstimator::GetEstimatorState() const {
  State r;
  r.error = error_;
  r.zeroed = zeroed_;
  r.position = position_;
  r.pot_position = filtered_position_;
  r.absolute_position = filtered_absolute_encoder_;
  return r;
}

void PulseIndexZeroingEstimator::Reset() {
  max_index_position_ = ::std::numeric_limits<double>::lowest();
  min_index_position_ = ::std::numeric_limits<double>::max();
  offset_ = 0;
  last_used_index_pulse_count_ = 0;
  zeroed_ = false;
  error_ = false;
}

void PulseIndexZeroingEstimator::StoreIndexPulseMaxAndMin(
    const IndexPosition &info) {
  // If we have a new index pulse.
  if (last_used_index_pulse_count_ != info.index_pulses) {
    // If the latest pulses's position is outside the range we've currently
    // seen, record it appropriately.
    if (info.latched_encoder > max_index_position_) {
      max_index_position_ = info.latched_encoder;
    }
    if (info.latched_encoder < min_index_position_) {
      min_index_position_ = info.latched_encoder;
    }
    last_used_index_pulse_count_ = info.index_pulses;
  }
}

int PulseIndexZeroingEstimator::IndexPulseCount() const {
  if (min_index_position_ > max_index_position_) {
    // This condition means we haven't seen a pulse yet.
    return 0;
  }

  // Calculate the number of pulses encountered so far.
  return 1 + static_cast<int>(
                 ::std::round((max_index_position_ - min_index_position_) /
                              constants_.index_difference));
}

void PulseIndexZeroingEstimator::UpdateEstimate(const IndexPosition &info) {
  StoreIndexPulseMaxAndMin(info);
  const int index_pulse_count = IndexPulseCount();
  if (index_pulse_count > constants_.index_pulse_count) {
    if (!error_) {
      LOG(ERROR, "Got more index pulses than expected. Got %d expected %d.\n",
          index_pulse_count, constants_.index_pulse_count);
      error_ = true;
    }
  }

  // TODO(austin): Detect if the encoder or index pulse is unplugged.
  // TODO(austin): Detect missing counts.

  if (index_pulse_count == constants_.index_pulse_count && !zeroed_) {
    offset_ = constants_.measured_index_position -
              constants_.known_index_pulse * constants_.index_difference -
              min_index_position_;
    zeroed_ = true;
  } else if (zeroed_ && !error_) {
    // Detect whether the index pulse is somewhere other than where we expect
    // it to be. First we compute the position of the most recent index pulse.
    double index_pulse_distance =
        info.latched_encoder + offset_ - constants_.measured_index_position;
    // Second we compute the position of the index pulse in terms of
    // the index difference. I.e. if this index pulse is two pulses away from
    // the index pulse that we know about then this number should be positive
    // or negative two.
    double relative_distance =
        index_pulse_distance / constants_.index_difference;
    // Now we compute how far away the measured index pulse is from the
    // expected index pulse.
    double error = relative_distance - ::std::round(relative_distance);
    // This lets us check if the index pulse is within an acceptable error
    // margin of where we expected it to be.
    if (::std::abs(error) > constants_.allowable_encoder_error) {
      LOG(ERROR,
          "Encoder ticks out of range since last index pulse. known index "
          "pulse: %f, expected index pulse: %f, actual index pulse: %f, "
          "allowable error: %f\n",
          constants_.measured_index_position,
          round(relative_distance) * constants_.index_difference +
              constants_.measured_index_position,
          info.latched_encoder + offset_,
          constants_.allowable_encoder_error * constants_.index_difference);
      error_ = true;
    }
  }

  position_ = info.encoder + offset_;
}

PulseIndexZeroingEstimator::State
PulseIndexZeroingEstimator::GetEstimatorState() const {
  State r;
  r.error = error_;
  r.zeroed = zeroed_;
  r.position = position_;
  r.min_index_position = min_index_position_;
  r.max_index_position = max_index_position_;
  r.index_pulses_seen = IndexPulseCount();
  return r;
}

}  // namespace zeroing
}  // namespace frc971
