// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "hoth_state.hpp"

#include <chrono>
#include <cstdint>
#include <cstring>
#include <exception>
#include <functional>
#include <future>
#include <stdplus/print.hpp>
#include <stdplus/raw.hpp>
#include <xyz/openbmc_project/Control/Hoth/State/error.hpp>

#include "ec_util_interface.hpp"
#include "google3/host_commands.h"

namespace google {
namespace hoth {
namespace {

constexpr uint32_t kTimerIntervalSeconds = 20;

template <typename T>
bool statisticsReponseHasEnoughWords(const ec_response_statistics &stats,
                                     const T &field) {
  uint64_t offset_required =
      (uint64_t)&field - (uint64_t)&stats + sizeof(field);
  return stats.valid_words * 4 >= offset_required;
}
}  // namespace

HothState::HothState(sdbusplus::bus::bus &bus, boost::asio::io_context &io,
                     const char *objPath, internal::HostCommand *hostCmd,
                     internal::EcUtil *ecutil)
    : HothStateObject(bus, objPath),
      bus(bus),
      io(io),
      hostCmd(hostCmd),
      ecUtil(ecutil),
      timer(io) {
  // Update metrics immediately while kicking off the timer.
  timerUpdateMetrics();
}

void HothState::updateMetrics() {
  try {
    statistics = ecUtil->getHothStatistics();

    // Emit the signal that property has changed.
    // Fall back to default values if response does not contain enought words.
    HothStateObject::resetFlags(
        statisticsReponseHasEnoughWords(statistics, statistics.hoth_reset_flags)
            ? (uint32_t)statistics.hoth_reset_flags
            : 0);
    HothStateObject::upTime(statisticsReponseHasEnoughWords(
                                statistics, statistics.time_since_hoth_boot_us)
                                ? (uint64_t)statistics.time_since_hoth_boot_us
                                : 0);
    HothStateObject::roInfoStrikes(
        statisticsReponseHasEnoughWords(statistics, statistics.ro_info_strikes)
            ? (uint32_t)statistics.ro_info_strikes
            : 0xffffffff);
    HothStateObject::rwInfoStrikes(
        statisticsReponseHasEnoughWords(statistics, statistics.rw_info_strikes)
            ? (uint32_t)statistics.rw_info_strikes
            : 0xffffffff);
    HothStateObject::payloadUpdateFailureCode(
        statisticsReponseHasEnoughWords(
            statistics, statistics.payload_update_failure_reason)
            ? (uint16_t)statistics.payload_update_failure_reason
            : 0xffff);
    HothStateObject::payloadConfirmFailureCode(
        statisticsReponseHasEnoughWords(
            statistics,
            statistics.payload_update_confirmation_cookie_failure_reason)
            ? (uint32_t)
                  statistics.payload_update_confirmation_cookie_failure_reason
            : 0xffffffff);
    HothStateObject::firmwareUpdateFailureCode(
        statisticsReponseHasEnoughWords(
            statistics, statistics.firmware_update_failure_reason)
            ? (uint16_t)statistics.firmware_update_failure_reason
            : 0xffff);
    HothStateObject::firmwareUpdateFailedMinor(
        statisticsReponseHasEnoughWords(
            statistics, statistics.failed_firmware_minor_version)
            ? (uint32_t)statistics.failed_firmware_minor_version
            : 0xffffffff);
    HothStateObject::bootloaderUpdateFailureCode(
        statisticsReponseHasEnoughWords(statistics,
                                        statistics.bootloader_update_error)
            ? (uint32_t)statistics.bootloader_update_error
            : 0xffffffff);
  } catch (const std::exception &e) {
    stdplus::print(stderr, "Fetching Hoth statistics had an exception: {}\n",
                   e.what());
  }

  try {
    ec_response_chip_info chip_info = ecUtil->getHothChipInfo();
    std::ostringstream serial_number;
    serial_number << chip_info.hardware_category << "-";
    serial_number << std::setfill('0') << std::setw(16) << std::noshowbase
                  << std::hex << chip_info.hardware_identity;
    HothStateObject::chipSerialNumber(serial_number.str());
    if (chip_info.hardware_category == 4) {
      HothStateObject::chipPartNumber("1100336");
      HothStateObject::chipRevision("H1D3P");
    } else if (chip_info.hardware_category == 1 &&
               chip_info.info_variant == 1) {
      HothStateObject::chipPartNumber("1059594");
      HothStateObject::chipRevision("H1B3P");
    } else if (chip_info.hardware_category == 1) {
      HothStateObject::chipPartNumber("07138244");
      HothStateObject::chipRevision("H1B2P");
    } else {
      HothStateObject::chipPartNumber("unknown");
      HothStateObject::chipRevision("unknown");
    }
  } catch (const std::exception &e) {
    stdplus::print(stderr, "Fetching Hoth chip info had an exception: {}\n",
                   e.what());
  }

  try {
    HothStateObject::hasPersistentPanicInfo(
        ecUtil->checkHothPersistentPanicInfo());
  } catch (const std::exception &e) {
    stdplus::print(stderr, "Fetching Hoth panic info had an exception: {}\n",
                   e.what());
  }

  try {
    ec_authz_record_get_response auth_record_resp = ecUtil->getHothAuthRecord();
    HothStateObject::hasValidAuthRecord(auth_record_resp.valid == 1);
    if (auth_record_resp.valid == 1) {
      HothStateObject::authRecordCapabilities(
          auth_record_resp.record.capabilities);
    }
  } catch (const std::exception &e) {
    stdplus::print(stderr, "Fetching Hoth auth record had an exception: {}\n",
                   e.what());
  }

  try {
    ec_response_key_rotation_status key_rotation_status =
        ecUtil->getHothKeyRotationStatus();

    HothStateObject::keyRotationVersion(key_rotation_status.version);
    HothStateObject::keyRotationImageFamily(key_rotation_status.image_family);
    HothStateObject::keyRotationImageFamilyVariant(
        key_rotation_status.image_family_variant);
    HothStateObject::keyRotationValidationMethod(
        key_rotation_status.validation_method);
    HothStateObject::keyRotationValidationKeyData(
        key_rotation_status.validation_key_data);
    HothStateObject::keyRotationValidationHashData(
        key_rotation_status.validation_hash_data);
  } catch (const std::exception &e) {
    HothStateObject::keyRotationValidationMethod(
        KEY_ROTATION_VALIDATION_METHOD_GET_ERROR);
  }
}

void HothState::timerUpdateMetrics() {
  try {
    updateMetrics();
  } catch (const std::exception &e) {
    stdplus::print(stderr, "Fetching Hoth metrics had an exception: {}\n",
                   e.what());
  }
  timer.expires_after(std::chrono::seconds(kTimerIntervalSeconds));
  // NOLINTNEXTLINE(modernize-avoid-bind)
  timer.async_wait(std::bind(&HothState::timerUpdateMetrics, this));
}

}  // namespace hoth

}  // namespace google
