#include "tlbmc/sensors/shared_mem_based_sensor.h"

#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/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/substitute.h"
#include "boost/asio.hpp"  // NOLINT: boost::asio is commonly used in BMC
#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: boost::filesystem is commonly used in BMC
#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 "entity_common_config.pb.h"
#include "i2c_common_config.pb.h"
#include "reading_range_config.pb.h"
#include "shared_mem_sensor_config.pb.h"
#include "threshold_config.pb.h"
#include "tlbmc/hal/shared_mem/server.h"
#include "resource.pb.h"
#include "sensor.pb.h"
#include "tlbmc/sensors/sensor.h"
#include "tlbmc/time/time.h"

namespace milotic_tlbmc {

absl::StatusOr<std::shared_ptr<Sensor>> SharedMemBasedSensor::Create(
    const SharedMemSensorConfig& config,
    const std::shared_ptr<boost::asio::io_context>& io_context,
    std::optional<NotificationCb> on_batch_notify) {
  return std::make_shared<SharedMemBasedSensor>(
      Token(), config.type(), config.unit(),
      // the sensor name rendering has a logic to trim a prefix before the first
      // "_"(which comes from the dbus sensor name convention). Add a prefix to
      // ensure the real name in redfish response is not partially trimmed.
      absl::StrCat("sharedmem_", config.name()), config.entity_common_config(),
      config.thresholds(), io_context, on_batch_notify);
}

SharedMemBasedSensor::SharedMemBasedSensor(
    Token token, SharedMemSensorType sensor_type, SensorUnit sensor_unit,
    const std::string& sensor_name,
    const EntityCommonConfig& entity_common_config,
    const ThresholdConfigs& threshold_configs,
    const std::shared_ptr<boost::asio::io_context>& io_context,
    std::optional<NotificationCb> on_batch_notify)
    : Sensor(CreateStaticAttributes(sensor_name, sensor_unit,
                                    /*i2c_common_config=*/{},
                                    entity_common_config, threshold_configs,
                                    /*reading_range_configs=*/{}),
             on_batch_notify),
      io_context_(io_context),
      sensor_type_(sensor_type),
      sensor_name_(sensor_name),
      board_config_name_(entity_common_config.board_config_name()) {}

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

    // Get the sensor value from the shared memory.
    auto sensor_value =
        milotic_tlbmc::SharedMemoryServer::GetInstance().ReadSensorValue(
            sensor->sensor_name_);

    if (!sensor_value.ok()) {
      State state;
      state.set_status(STATUS_STALE);
      state.set_status_message(absl::Substitute(
          "Failed to read sensor value from shared memory: $0 with error: $1",
          sensor->sensor_name_, sensor_value.status().message()));
      sensor->UpdateState(std::move(state));
      if (callback) {
        callback(sensor->GetSensorData());
      }
      LOG(INFO) << "SharedMemBasedSensor::RefreshOnceAsync failed: "
                << sensor->sensor_name_ << " " << sensor_value.status();
      return;
    }

    SensorValue sensor_data;
    // milliseconds to timestamp
    *sensor_data.mutable_timestamp() =
        MilliSecondsToTimestamp(sensor_value->second);
    sensor_data.set_reading(static_cast<double>(sensor_value->first));
    LOG(INFO) << "SharedMemBasedSensor::RefreshOnceAsync success: "
              << sensor->sensor_name_ << " " << sensor_data.reading();
    sensor->StoreSensorData(
        std::make_shared<const SensorValue>(std::move(sensor_data)));
    State state;
    state.set_status(STATUS_READY);
    sensor->UpdateState(std::move(state));

    if (callback) {
      callback(sensor->GetSensorData());
    }
  });
}

}  // namespace milotic_tlbmc
