// 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 "asset.hpp"

#include "google3/ec_commands.h"

#include "message_util.hpp"

#include <stdplus/print.hpp>
#include <stdplus/raw.hpp>
#include <xyz/openbmc_project/Control/Hoth/error.hpp>

#include <format>
#include <span>
#include <string>
#include <unordered_map>
#include <variant>
#include <vector>

namespace google
{
namespace hoth
{

using sdbusplus::error::xyz::openbmc_project::control::hoth::ResponseFailure;
using internal::EC_RES_SUCCESS;
using internal::HostCommand;
using internal::RspHeader;

namespace
{
constexpr std::string_view kFieldUnknown = "unknown";

constexpr std::string_view kProductNameH1B1P = "H1B1P";
constexpr std::string_view kProductNameH1B2P = "H1B2P";
constexpr std::string_view kProductNameH1D2P = "H1D2P";

constexpr std::string_view kPartNumberH1B1P = "07133954";
constexpr std::string_view kPartNumberH1B2P = "07138244";
constexpr std::string_view kPartNumberH1D2P = "G660-00438-01";

constexpr std::string kManufacturer = "Google";
constexpr std::string kModel = "Titan";

constexpr uint8_t kCryptaMiscCommand = 3;
constexpr uint8_t kCryptaMiscGetCryptaInfoCommand = 0;

std::string_view GetRevisionName(uint16_t hardware_category)
{
    switch (hardware_category)
    {
        case CRYPTA_HW_CAT_HOTH_B1:
            return kProductNameH1B1P;
        case CRYPTA_HW_CAT_HOTH_B2:
            return kProductNameH1B2P;
        case CRYPTA_HW_CAT_HOTH_D2:
            return kProductNameH1D2P;
        default:
            return kFieldUnknown;
    }
}

std::string_view GetPartNumber(uint16_t hardware_category)
{
    switch (hardware_category)
    {
        case CRYPTA_HW_CAT_HOTH_B1:
            return kPartNumberH1B1P;
        case CRYPTA_HW_CAT_HOTH_B2:
            return kPartNumberH1B2P;
        case CRYPTA_HW_CAT_HOTH_D2:
            return kPartNumberH1D2P;
        default:
            return kFieldUnknown;
    }
}

std::string GetSerialNumber(const crypta_command_info_hoth_id& hoth_id)
{
    return std::format("{}-{:#16x}",
                       static_cast<uint16_t>(hoth_id.hardware_category),
                       static_cast<uint64_t>(hoth_id.hardware_id));
}

} // namespace

static ec_response_crypta_info getCryptaInfo(HostCommand* hostCmd)
{
    struct ec_request_crypta_info request;
    request.major_command = kCryptaMiscCommand;
    request.minor_command = kCryptaMiscGetCryptaInfoCommand;
    request.param_count = 0;

    std::vector<uint8_t> buf = hostCmd->sendCommand(
        EC_CMD_BOARD_SPECIFIC_BASE + EC_PRV_CMD_HOTH_CRYPTA, 0, &request,
        sizeof(request));

    // Extract the response header out when returning the span
    std::span<const uint8_t> output = buf;
    auto& rsp = stdplus::raw::extractRef<RspHeader>(output);

    if (rsp.result != EC_RES_SUCCESS)
    {
        stdplus::print(
            stderr,
            "Asset Crypta command received a bad response from Hoth {:#x}\n",
            static_cast<uint8_t>(rsp.result));
        throw ResponseFailure();
    }

    return stdplus::raw::copyFrom<ec_response_crypta_info>(output);
}

Asset::Asset(sdbusplus::bus::bus& bus, const std::string& objPath,
             const std::string& boardPath, HostCommand* hostCmd) :
    AssetAssociationObject(bus, objPath.c_str(),
                           AssetAssociationObject::action::defer_emit),
    hostCmd(hostCmd)
{
    ec_response_crypta_info response = getCryptaInfo(Asset::hostCmd);
    crypta_command_info_hoth_id hoth_id =
        response.crypta_info.crypta_id.hoth_id;

    /* Set Crypta Properties */
    partNumber(std::string(GetPartNumber(hoth_id.hardware_category)), true);
    subModel(std::string(GetRevisionName(hoth_id.hardware_category)), true);
    serialNumber(GetSerialNumber(hoth_id), true);
    manufacturer(kManufacturer, true);
    model(kModel, true);

    /* Set association with chassis/board object that contains the hoth */
    associations({std::make_tuple("chassis", "assembly", boardPath)}, true);

    AssetAssociationObject::emit_object_added();
}

} // namespace hoth

} // namespace google
