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

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

#include <cstring>
#include <span>

namespace google
{
namespace hoth
{
namespace internal
{

using sdbusplus::error::xyz::openbmc_project::control::hoth::CommandFailure;
using sdbusplus::error::xyz::openbmc_project::control::hoth::ResponseFailure;

void populateReqHeader(uint16_t command, uint8_t command_version,
                       const void* request, size_t request_size,
                       ReqHeader* request_header)
{
    if (!request_header)
    {
        stdplus::print(stderr, "Request header argument cannot be NULL\n");
        throw CommandFailure();
    }

    if (request_size > 0 && !request)
    {
        stdplus::print(stderr,
                       "Request data argument cannot be NULL with size > 0\n");
        throw CommandFailure();
    }

    if (request_size > UINT16_MAX)
    {
        stdplus::print(stderr,
                       "Error, request_size({}) bigger than UINT16_MAX\n",
                       request_size);
        throw CommandFailure();
    }

    request_header->struct_version = SUPPORTED_STRUCT_VERSION;
    request_header->checksum = 0;
    request_header->command = command;
    request_header->command_version = command_version;
    request_header->reserved = 0;
    request_header->data_len = static_cast<uint16_t>(request_size);
    // Note that we've set |checksum| to zero earlier, so this is deterministic.
    request_header->checksum -= calculateChecksum(
        stdplus::raw::asSpan<uint8_t>(*request_header),
        std::span<const uint8_t>(reinterpret_cast<const uint8_t*>(request),
                                 request_size));
}

size_t reqLen(const std::vector<uint8_t>& req)
{
    struct ReqHeader header;

    if (req.size() < sizeof(header))
    {
        stdplus::print(stderr, "Command is too short: `{} < {}`\n", req.size(),
                       sizeof(header));
        throw CommandFailure();
    }

    std::memcpy(&header, req.data(), sizeof(header));

    if (header.struct_version != SUPPORTED_STRUCT_VERSION)
    {
        stdplus::print(stderr, "Unsupported struct_version in command {}\n",
                       static_cast<uint16_t>(header.struct_version));
        throw CommandFailure();
    }

    return sizeof(header) + header.data_len;
}

size_t rspLen(const std::vector<uint8_t>& rsp)
{
    struct RspHeader header;

    if (rsp.size() < sizeof(header))
    {
        stdplus::print(stderr, "Response is too short `{} < {}`\n", rsp.size(),
                       sizeof(header));
        throw ResponseFailure();
    }

    std::memcpy(&header, rsp.data(), sizeof(header));

    if (header.struct_version != SUPPORTED_STRUCT_VERSION)
    {
        stdplus::print(stderr, "Unsupported struct_version in response {}\n",
                       static_cast<uint16_t>(header.struct_version));
        throw ResponseFailure();
    }

    return sizeof(header) + header.data_len;
}

std::vector<uint8_t> generateErrorResponse(uint8_t error)
{
    RspHeader rsp = {};
    rsp.struct_version = SUPPORTED_STRUCT_VERSION;
    rsp.result = error;
    rsp.checksum -= calculateChecksum(stdplus::raw::asSpan<uint8_t>(rsp));
    std::vector<uint8_t> ret;
    ret.resize(sizeof(rsp));
    std::memcpy(ret.data(), &rsp, sizeof(rsp));
    return ret;
}

} // namespace internal

} // namespace hoth

} // namespace google
