#include "tlbmc/sensors/hwmon_based_sensor.h"

#include <chrono>  // NOLINT
#include <cstddef>
#include <memory>
#include <optional>
#include <string>
#include <utility>

#include "google/protobuf/duration.pb.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/log.h"
#include "absl/strings/match.h"
#include "boost/asio.hpp"  // NOLINT: boost::asio is commonly used in BMC
#include "boost/asio/error.hpp"  // NOLINT
#include "boost/asio/random_access_file.hpp"  // NOLINT: boost::asio is commonly used in BMC
#include "boost/filesystem.hpp"  // NOLINT: boost::filesystem is commonly used in BMC
#include "boost/filesystem/operations.hpp"  // NOLINT
#include "boost/system/detail/error_code.hpp"  // NOLINT: boost::asio is commonly used in BMC
// NOLINTNEXTLINE: keep this so BUILD file will keep liburing
#include "liburing.h"  // IWYU pragma: keep
#include "hal_common_config.pb.h"
#include "hwmon_temp_sensor_config.pb.h"
#include "resource.pb.h"
#include "sensor.pb.h"
#include "tlbmc/sensors/hwmon_input_device.h"
#include "tlbmc/sensors/sensor.h"

namespace milotic_tlbmc {

void HwmonBasedSensor::SetUpInput() {
  // If the input device is already usable, it means the sensor is already in
  // a valid state. We should not be modifying any of its internals.
  if (IsInputDeviceUsable()) {
    LOG(WARNING) << "Input device is already usable for " << input_dev_path_
                 << ". Skipping setup.";
    return;
  }
  // TODO(nanzhou): This logic should be eventually become a power signal based
  // device deletion and recreation. E.g.,
  // /sys/bus/i2c/devices/i2c-35/35-005c/hwmon/hwmon0/temp1_input
  // This also assumes the label and device mapping does not changes after
  // recreation.
  boost::filesystem::path input_dev_path(input_dev_path_);
  bool found_hwmon = false;
  boost::filesystem::path hwmon_folder =
      input_dev_path.parent_path().parent_path();
  boost::system::error_code error;
  for (const auto& entry :
       boost::filesystem::directory_iterator(hwmon_folder, error)) {
    if (error) {
      break;
    }
    // Look for something like hwmon10
    if (absl::StartsWith(entry.path().filename().string(), "hwmon")) {
      SetInputDevicePath((entry.path() / input_dev_path.filename()).string());
      found_hwmon = true;
      break;
    }
  }
  if (!found_hwmon) {
    SetInputDeviceUsable(false);
    return;
  }

  input_device_ =
      std::make_shared<HwmonInputDevice>(io_context_, input_dev_path_);
  SetInputDeviceUsable(true);
}

HwmonBasedSensor::HwmonBasedSensor(
    const std::string& input_dev_path,
    const std::shared_ptr<boost::asio::io_context>& io_context,
    SensorAttributesStatic&& sensor_attributes_static,
    const ThresholdConfigs& threshold_configs,
    std::optional<NotificationCb> on_batch_notify)
    : Sensor(std::move(sensor_attributes_static), threshold_configs,
             on_batch_notify),
      input_dev_path_(input_dev_path),
      io_context_(io_context),
      input_device_usable_(false) {
  if (!input_dev_path.empty()) {
    input_device_ =
        std::make_shared<HwmonInputDevice>(io_context_, input_dev_path_);
    SetInputDeviceUsable(true);
  }
}

HwmonBasedSensor::~HwmonBasedSensor() { input_device_usable_ = false; }

void HwmonBasedSensor::RefreshOnceAsync(
    absl::AnyInvocable<void(const std::shared_ptr<const SensorValue>&)>
        callback) {
  std::weak_ptr<HwmonBasedSensor> self = weak_from_this();
  boost::asio::post(*io_context_, [self{std::move(self)},
                                   callback = std::move(callback)]() mutable {
    std::shared_ptr<HwmonBasedSensor> sensor = self.lock();
    if (!sensor) {
      LOG(WARNING) << "Sensor is already destroyed; cancel the refresh";
      return;
    }

    std::chrono::steady_clock::time_point last_refresh_start_time =
        sensor->GetLastRefreshStartTime();
    if (last_refresh_start_time !=
        std::chrono::steady_clock::time_point::min()) {
      sensor->UpdateSoftwarePollingStartMetrics(
          std::chrono::steady_clock::now() - last_refresh_start_time);
    }
    sensor->SetLastRefreshStartTime(std::chrono::steady_clock::now());
    // The device might be deleted. E.g., the endpoint device lost
    // power. In this case, we will try to set up the device again and
    // bypass the refresh.
    if (!sensor->IsInputDeviceUsable() ||
        !boost::filesystem::exists(sensor->GetInputDevicePath())) {
      // Make the input device unusable to allow SetUpInput to be called.
      sensor->SetInputDeviceUsable(false);
      sensor->SetUpInput();
      sensor->HandleRefreshResult(boost::asio::error::no_such_device, 0);
      if (callback) {
        callback(sensor->GetSensorData());
      }
      return;
    }
    std::chrono::time_point<std::chrono::steady_clock> start_time =
        std::chrono::steady_clock::now();

    sensor->GetInputDevice()->ReadAndProcess(
        [self, start_time, callback = std::move(callback)](
            const boost::system::error_code& error, size_t bytes_read) mutable {
          std::shared_ptr<HwmonBasedSensor> sensor = self.lock();
          if (!sensor) {
            return;
          }
          std::chrono::steady_clock::duration latency =
              std::chrono::steady_clock::now() - start_time;
          sensor->UpdateHardwarePollingMetrics(latency);
          // If the device is deleted, we will try to set up the device again
          if (error == boost::asio::error::no_such_device) {
            sensor->SetInputDeviceUsable(false);
            sensor->SetUpInput();
          }
          sensor->HandleRefreshResult(error, bytes_read);
          if (callback) {
            callback(sensor->GetSensorData());
          }

          std::chrono::steady_clock::time_point last_refresh_end_time =
              sensor->GetLastRefreshEndTime();
          if (last_refresh_end_time !=
              std::chrono::steady_clock::time_point::min()) {
            sensor->UpdateSoftwarePollingEndMetrics(
                std::chrono::steady_clock::now() - last_refresh_end_time);
          }
          sensor->SetLastRefreshEndTime(std::chrono::steady_clock::now());
        },
        sensor->GetMutableReadBuffer());
  });
}

}  // namespace milotic_tlbmc
