#include "tlbmc/thermal/controller/fan_pid_controller.h"

#include <algorithm>
#include <cmath>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include <nlohmann/json.hpp>
#include "tlbmc/thermal/controller/algorithm/pid.h"
#include "tlbmc/thermal/zone_manager.h"

namespace milotic_tlbmc {
namespace thermal {

absl::StatusOr<std::unique_ptr<FanPidController>> FanPidController::Create(
    FanPidControllerParameters params) {
  if (params.input_fans.empty()) {
    return absl::InvalidArgumentError(absl::StrFormat(
        "No input fan is assigned to fan PID controller `%s`!", params.id));
  }

  if (params.output_fans.empty()) {
    return absl::InvalidArgumentError(absl::StrFormat(
        "No output fan is assigned to fan PID controller `%s`!", params.id));
  }

  auto fan_pid_controller = absl::WrapUnique(new FanPidController(
      params.id, params.zone_manager, std::move(params.pid_loop),
      std::move(params.input_fans), std::move(params.output_fans)));

  return fan_pid_controller;
}

void FanPidController::ProcessThermalLoop() {
  double input = ProcessInput();
  double setpoint = GetSetpoint();

  zone_owner_->TryLogThermalDebugMessage(
      absl::StrFormat("Fan PID controller `%s` in zone `%d` takes "
                      "input RPM `%f` and setpoint `%f`",
                      GetId(), zone_owner_->GetId(), input, setpoint));

  ProcessOutput(GetPidLoop()->ExecutePidLoop(
      input, setpoint, zone_owner_->GetDebugPidEnabled()));
}

double FanPidController::ProcessInput() {
  std::optional<double> min_rpm;
  for (const std::string& fan_name : GetInputFans()) {
    double value = zone_owner_->GetSensorReadings(fan_name).scaled_value;
    if (!std::isfinite(value) || value < 1.0) {
      continue;
    }
    min_rpm = min_rpm ? std::min(value, *min_rpm) : value;
  }
  return min_rpm.value_or(kDefaultFanRpmValue);
}

void FanPidController::ProcessOutput(double pwm) {
  bool failsafe_transition = false;

  // Failsafe mode is only for non-tuning modes: In tuning mode, just print the
  // calculation results, instead of checking whether to enter the failsafe
  // mode.
  if (zone_owner_->GetTuningEnabled()) {
    ZoneManager::LogThermalMessage(
        absl::StrFormat("Fan PID controller `%s` in zone `%d` is in tuning "
                        "mode with output PWM `%f` by `%s`",
                        GetId(), zone_owner_->GetId(), pwm, GetId()));
  } else {
    bool current_failsafe_state = zone_owner_->GetFailsafeMode();

    if (previous_failsafe_state_ != current_failsafe_state) {
      previous_failsafe_state_ = current_failsafe_state;
      failsafe_transition = true;
    }

    if (current_failsafe_state) {
      double failsafe_percent = zone_owner_->GetFailsafePercent();
      // Ensure PWM is never lower than the failsafe PWM under failsafe mode.
      pwm = std::max(pwm, failsafe_percent);
    }

    if (zone_owner_->GetDebugEnabled()) {
      zone_owner_->TryLogThermalDebugMessage(
          absl::StrFormat("Fan PID controller `%s` in zone `%d` is in %s mode "
                          "with output PWM `%f`",
                          GetId(), zone_owner_->GetId(),
                          current_failsafe_state ? "failsafe" : "normal", pwm));
    } else if (failsafe_transition) {
      // Output failsafe log as long as the failsafe state changes, once only.
      ZoneManager::LogThermalMessage(
          absl::StrFormat("Fan PID controller `%s` in zone `%d` is in failsafe "
                          "mode with output PWM `%f`",
                          GetId(), zone_owner_->GetId(), pwm));
    }
  }

  // Update the real fan speeds.
  for (const std::string& fan_name : GetOutputFans()) {
    zone_owner_->UpdateLocallyRecordedFanPwmAndCheckFailsafe(fan_name, pwm);
  }
  if (zone_owner_->GetDebugEnabled()) {
    zone_owner_->AppendSampledData(absl::StrCat(pwm, ","));
  }
}

void FanPidController::SetCoefficients(
    const FanPidControllerCoefficients& coefficients) {
  if (coefficients.coeff_proportional.has_value()) {
    pid_loop_->SetCoeffProportional(*coefficients.coeff_proportional);
  }
  if (coefficients.coeff_integral.has_value()) {
    pid_loop_->SetCoeffIntegral(*coefficients.coeff_integral);
  }
  if (coefficients.coeff_derivative.has_value()) {
    pid_loop_->SetCoeffDerivative(*coefficients.coeff_derivative);
  }
  if (coefficients.feed_forward_offset.has_value()) {
    pid_loop_->SetFeedForwardOffset(*coefficients.feed_forward_offset);
  }
  if (coefficients.feed_forward_gain.has_value()) {
    pid_loop_->SetFeedForwardGain(*coefficients.feed_forward_gain);
  }
}

nlohmann::json FanPidController::ToJson() const {
  nlohmann::json json;
  json["DCoefficient"] = pid_loop_->GetCoeffDerivative();
  json["FFGainCoefficient"] = pid_loop_->GetFeedForwardGain();
  json["FFOffCoefficient"] = pid_loop_->GetFeedForwardOffset();
  json["ICoefficient"] = pid_loop_->GetCoeffIntegral();
  json["ILimitMax"] = pid_loop_->GetIntegralLimitMax();
  json["ILimitMin"] = pid_loop_->GetIntegralLimitMin();
  json["OutLimitMax"] = pid_loop_->GetOutputLimitMax();
  json["OutLimitMin"] = pid_loop_->GetOutputLimitMin();
  json["PCoefficient"] = pid_loop_->GetCoeffProportional();
  json["SlewNeg"] = pid_loop_->GetSlewNeg();
  json["SlewPos"] = pid_loop_->GetSlewPos();
  json["Inputs"] = nlohmann::json::array();
  for (const auto& input : input_fans_) {
    json["Inputs"].push_back(input);
  }
  return json;
}

}  // namespace thermal
}  // namespace milotic_tlbmc
