/*
// Copyright (c) 2018 Intel Corporation
//
// 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 "error_messages.hpp"

#include <array>
#include <cstddef>
#include <cstdint>
#include <span>  // NOLINT
#include <string>
#include <string_view>
#include <utility>

#include "boost/beast/http/field.hpp"  // NOLINT
#include "boost/beast/http/status.hpp"  // NOLINT
#include "http_response.hpp"
#include "logging.hpp"
#include "source_location.hpp"
#include "registries.hpp"
#include "registries/base_message_registry.hpp"
#include <nlohmann/json.hpp>

// IWYU pragma: no_include <stddef.h>

namespace redfish {

namespace messages {

static void addMessageToErrorJson(nlohmann::json& target,
                                  const nlohmann::json& message) {
  auto& error = target["error"];

  // If this is the first error message, fill in the information from the
  // first error message to the top level struct
  if (!error.is_object()) {
    // Have default error messages so that we dont end up with empty errors.
    error["code"] = std::string(messageVersionPrefix) + "GeneralError";
    error["message"] =
        "A general error has occurred. See Resolution for "
        "information on how to resolve the error.";

    auto message_id_iterator = message.find("MessageId");
    if (message_id_iterator != message.end()) {
      error["code"] = *message_id_iterator;
    }

    auto message_field_iterator = message.find("Message");
    if (message_field_iterator != message.end()) {
      error["message"] = *message_field_iterator;
    }
  } else {
    // More than 1 error occurred, so the message has to be generic
    error["code"] = std::string(messageVersionPrefix) + "GeneralError";
    error["message"] =
        "A general error has occurred. See Resolution for "
        "information on how to resolve the error.";
  }

  // This check could technically be done in the default construction
  // branch above, but because we need the pointer to the extended info field
  // anyway, it's more efficient to do it here.
  auto& extended_info = error[messages::messageAnnotation];
  if (!extended_info.is_array()) {
    extended_info = nlohmann::json::array();
  }

  extended_info.emplace_back(message);
}

void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source) {
  if (!source.is_object()) {
    return;
  }
  auto error_it = source.find("error");
  if (error_it == source.end()) {
    // caller puts error message in root
    messages::addMessageToErrorJson(target, source);
    return;
  }
  auto extended_info_it = error_it->find(messages::messageAnnotation);
  if (extended_info_it == error_it->end()) {
    return;
  }
  const nlohmann::json::array_t* extended_info =
      (*extended_info_it).get_ptr<const nlohmann::json::array_t*>();
  if (extended_info == nullptr) {
    source.erase(error_it);
    return;
  }
  for (const nlohmann::json& message : *extended_info) {
    addMessageToErrorJson(target, message);
  }
  source.erase(error_it);
}

static void addMessageToJsonRoot(nlohmann::json& target,
                                 const nlohmann::json& message) {
  if (!target[messages::messageAnnotation].is_array()) {
    // Force object to be an array
    target[messages::messageAnnotation] = nlohmann::json::array();
  }

  target[messages::messageAnnotation].emplace_back(message);
}

static void addMessageToJson(nlohmann::json& target,
                             const nlohmann::json& message,
                             std::string_view fieldPath) {
  std::string extended_info(fieldPath);
  extended_info += messages::messageAnnotation;

  nlohmann::json& field = target[extended_info];
  if (!field.is_array()) {
    // Force object to be an array
    field = nlohmann::json::array();
  }

  // Object exists and it is an array so we can just push in the message
  field.emplace_back(message);
}

static nlohmann::json getLog(redfish::registries::base::Index name,
                             std::span<const std::string_view> args) {
  size_t index = static_cast<size_t>(name);
  if (index >= redfish::registries::base::registry.size()) {
    return {};
  }
  return getLogFromRegistry(redfish::registries::base::header,
                            redfish::registries::base::registry, index, args);
}

/**
 * @internal
 * @brief Formats ResourceInUse message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resourceInUse() {
  return getLog(redfish::registries::base::Index::resourceInUse, {});
}

void resourceInUse(crow::Response& res) {
  res.result(boost::beast::http::status::service_unavailable);
  addMessageToErrorJson(res.jsonValue, resourceInUse());
}

/**
 * @internal
 * @brief Formats MalformedJSON message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json malformedJSON() {
  return getLog(redfish::registries::base::Index::malformedJSON, {});
}

void malformedJSON(crow::Response& res) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, malformedJSON());
}

/**
 * @internal
 * @brief Formats ResourceMissingAtURI message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resourceMissingAtURI(boost::urls::url_view arg1)  // NOLINT
{
  std::array<std::string_view, 1> args{arg1.buffer()};
  return getLog(redfish::registries::base::Index::resourceMissingAtURI, args);
}

void resourceMissingAtURI(crow::Response& res,
                          boost::urls::url_view arg1)  // NOLINT
{
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, resourceMissingAtURI(arg1));
}
/**
 * @internal
 * @brief Formats ActionParameterValueError message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json actionParameterValueError(std::string_view arg1,
                                         std::string_view arg2) {
  return getLog(redfish::registries::base::Index::actionParameterValueError,
                std::to_array({arg1, arg2}));
}

void actionParameterValueError(crow::Response& res, std::string_view arg1,
                               std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, actionParameterValueError(arg1, arg2));
}

/**
 * @internal
 * @brief Formats ActionParameterValueFormatError message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json actionParameterValueFormatError(std::string_view arg1,
                                               std::string_view arg2,
                                               std::string_view arg3) {
  return getLog(
      redfish::registries::base::Index::actionParameterValueFormatError,
      std::to_array({arg1, arg2, arg3}));
}

void actionParameterValueFormatError(crow::Response& res, std::string_view arg1,
                                     std::string_view arg2,
                                     std::string_view arg3) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue,
                        actionParameterValueFormatError(arg1, arg2, arg3));
}

/**
 * @internal
 * @brief Formats ActionParameterValueNotInList message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json actionParameterValueNotInList(std::string_view arg1,
                                             std::string_view arg2,
                                             std::string_view arg3) {
  return getLog(redfish::registries::base::Index::actionParameterValueNotInList,
                std::to_array({arg1, arg2, arg3}));
}

void actionParameterValueNotInList(crow::Response& res, std::string_view arg1,
                                   std::string_view arg2,
                                   std::string_view arg3) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue,
                        actionParameterValueNotInList(arg1, arg2, arg3));
}

/**
 * @internal
 * @brief Formats InternalError message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json internalError() {
  return getLog(redfish::registries::base::Index::internalError, {});
}

void internalError(crow::Response& res,
                   const bmcweb::source_location location) {
  BMCWEB_LOG_CRITICAL << "Internal Error " << location.file_name() << "("
                      << location.line() << ":" << location.column() << ") `"
                      << location.function_name() << "`: ";
  res.result(boost::beast::http::status::internal_server_error);
  addMessageToErrorJson(res.jsonValue, internalError());
}

/**
 * @internal
 * @brief Formats UnrecognizedRequestBody message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json unrecognizedRequestBody() {
  return getLog(redfish::registries::base::Index::unrecognizedRequestBody, {});
}

void unrecognizedRequestBody(crow::Response& res) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, unrecognizedRequestBody());
}

/**
 * @internal
 * @brief Formats ResourceAtUriUnauthorized message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resourceAtUriUnauthorized(boost::urls::url_view arg1,  // NOLINT
                                         std::string_view arg2) {
  return getLog(redfish::registries::base::Index::resourceAtUriUnauthorized,
                std::to_array<std::string_view>({arg1.buffer(), arg2}));
}

void resourceAtUriUnauthorized(crow::Response& res,
                               boost::urls::url_view arg1,  // NOLINT
                               std::string_view arg2) {
  res.result(boost::beast::http::status::unauthorized);
  addMessageToErrorJson(res.jsonValue, resourceAtUriUnauthorized(arg1, arg2));
}

/**
 * @internal
 * @brief Formats ActionParameterUnknown message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json actionParameterUnknown(std::string_view arg1,
                                      std::string_view arg2) {
  return getLog(redfish::registries::base::Index::actionParameterUnknown,
                std::to_array({arg1, arg2}));
}

void actionParameterUnknown(crow::Response& res, std::string_view arg1,
                            std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, actionParameterUnknown(arg1, arg2));
}

/**
 * @internal
 * @brief Formats ResourceCannotBeDeleted message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resourceCannotBeDeleted() {
  return getLog(redfish::registries::base::Index::resourceCannotBeDeleted, {});
}

void resourceCannotBeDeleted(crow::Response& res) {
  res.result(boost::beast::http::status::method_not_allowed);
  addMessageToErrorJson(res.jsonValue, resourceCannotBeDeleted());
}

/**
 * @internal
 * @brief Formats PropertyDuplicate message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyDuplicate(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::propertyDuplicate,
                std::to_array({arg1}));
}

void propertyDuplicate(crow::Response& res, std::string_view arg1) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToJson(res.jsonValue, propertyDuplicate(arg1), arg1);
}

/**
 * @internal
 * @brief Formats ServiceTemporarilyUnavailable message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json serviceTemporarilyUnavailable(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::serviceTemporarilyUnavailable,
                std::to_array({arg1}));
}

void serviceTemporarilyUnavailable(crow::Response& res, std::string_view arg1) {
  res.addHeader(boost::beast::http::field::retry_after, arg1);
  res.result(boost::beast::http::status::service_unavailable);
  addMessageToErrorJson(res.jsonValue, serviceTemporarilyUnavailable(arg1));
}

/**
 * @internal
 * @brief Formats ResourceAlreadyExists message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resourceAlreadyExists(std::string_view arg1,
                                     std::string_view arg2,
                                     std::string_view arg3) {
  return getLog(redfish::registries::base::Index::resourceAlreadyExists,
                std::to_array({arg1, arg2, arg3}));
}

void resourceAlreadyExists(crow::Response& res, std::string_view arg1,
                           std::string_view arg2, std::string_view arg3) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToJson(res.jsonValue, resourceAlreadyExists(arg1, arg2, arg3),
                   arg2);
}

/**
 * @internal
 * @brief Formats AccountForSessionNoLongerExists message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json accountForSessionNoLongerExists() {
  return getLog(
      redfish::registries::base::Index::accountForSessionNoLongerExists, {});
}

void accountForSessionNoLongerExists(crow::Response& res) {
  res.result(boost::beast::http::status::forbidden);
  addMessageToErrorJson(res.jsonValue, accountForSessionNoLongerExists());
}

/**
 * @internal
 * @brief Formats CreateFailedMissingReqProperties message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json createFailedMissingReqProperties(std::string_view arg1) {
  return getLog(
      redfish::registries::base::Index::createFailedMissingReqProperties,
      std::to_array({arg1}));
}

void createFailedMissingReqProperties(crow::Response& res,
                                      std::string_view arg1) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToJson(res.jsonValue, createFailedMissingReqProperties(arg1), arg1);
}
/**
 * @internal
 * @brief Formats PropertyValueError message into JSON for the specified
 * property
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyValueError(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::propertyValueError,
                std::to_array({arg1}));
}

void propertyValueError(crow::Response& res, std::string_view arg1) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToJson(res.jsonValue, propertyValueError(arg1), arg1);
}

/**
 * @internal
 * @brief Formats PropertyValueFormatError message into JSON for the specified
 * property
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyValueFormatError(std::string_view arg1,
                                        std::string_view arg2) {
  return getLog(redfish::registries::base::Index::propertyValueFormatError,
                std::to_array({arg1, arg2}));
}

void propertyValueFormatError(crow::Response& res, std::string_view arg1,
                              std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToJson(res.jsonValue, propertyValueFormatError(arg1, arg2), arg2);
}

/**
 * @internal
 * @brief Formats PropertyValueNotInList message into JSON for the specified
 * property
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyValueNotInList(std::string_view arg1,
                                      std::string_view arg2) {
  return getLog(redfish::registries::base::Index::propertyValueNotInList,
                std::to_array({arg1, arg2}));
}

void propertyValueNotInList(crow::Response& res, std::string_view arg1,
                            std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToJson(res.jsonValue, propertyValueNotInList(arg1, arg2), arg2);
}

/**
 * @internal
 * @brief Formats PropertyValueOutOfRange message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyValueOutOfRange(std::string_view arg1,
                                       std::string_view arg2) {
  return getLog(redfish::registries::base::Index::propertyValueOutOfRange,
                std::to_array({arg1, arg2}));
}

void propertyValueOutOfRange(crow::Response& res, std::string_view arg1,
                             std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, propertyValueOutOfRange(arg1, arg2));
}

/**
 * @internal
 * @brief Formats ResourceAtUriInUnknownFormat message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resourceAtUriInUnknownFormat(
    boost::urls::url_view arg1)  // NOLINT
{
  return getLog(redfish::registries::base::Index::resourceAtUriInUnknownFormat,
                std::to_array<std::string_view>({arg1.buffer()}));
}

void resourceAtUriInUnknownFormat(crow::Response& res,
                                  boost::urls::url_view arg1)  // NOLINT
{
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, resourceAtUriInUnknownFormat(arg1));
}

/**
 * @internal
 * @brief Formats ServiceDisabled message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json serviceDisabled(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::serviceDisabled,
                std::to_array({arg1}));
}

void serviceDisabled(crow::Response& res, std::string_view arg1) {
  res.result(boost::beast::http::status::service_unavailable);
  addMessageToErrorJson(res.jsonValue, serviceDisabled(arg1));
}

/**
 * @internal
 * @brief Formats ServiceInUnknownState message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json serviceInUnknownState() {
  return getLog(redfish::registries::base::Index::serviceInUnknownState, {});
}

void serviceInUnknownState(crow::Response& res) {
  res.result(boost::beast::http::status::service_unavailable);
  addMessageToErrorJson(res.jsonValue, serviceInUnknownState());
}

/**
 * @internal
 * @brief Formats EventSubscriptionLimitExceeded message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json eventSubscriptionLimitExceeded() {
  return getLog(
      redfish::registries::base::Index::eventSubscriptionLimitExceeded, {});
}

void eventSubscriptionLimitExceeded(crow::Response& res) {
  res.result(boost::beast::http::status::service_unavailable);
  addMessageToErrorJson(res.jsonValue, eventSubscriptionLimitExceeded());
}

/**
 * @internal
 * @brief Formats ActionParameterMissing message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json actionParameterMissing(std::string_view arg1,
                                      std::string_view arg2) {
  return getLog(redfish::registries::base::Index::actionParameterMissing,
                std::to_array({arg1, arg2}));
}

void actionParameterMissing(crow::Response& res, std::string_view arg1,
                            std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, actionParameterMissing(arg1, arg2));
}

/**
 * @internal
 * @brief Formats StringValueTooLong message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json stringValueTooLong(std::string_view arg1, int arg2) {
  std::string arg_to_string = std::to_string(arg2);
  return getLog(redfish::registries::base::Index::stringValueTooLong,
                std::to_array({arg1, std::string_view(arg_to_string)}));
}

void stringValueTooLong(crow::Response& res, std::string_view arg1, int arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, stringValueTooLong(arg1, arg2));
}

/**
 * @internal
 * @brief Formats SessionTerminated message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json sessionTerminated() {
  return getLog(redfish::registries::base::Index::sessionTerminated, {});
}

void sessionTerminated(crow::Response& res) {
  res.result(boost::beast::http::status::ok);
  addMessageToJsonRoot(res.jsonValue, sessionTerminated());
}

/**
 * @internal
 * @brief Formats SubscriptionTerminated message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json subscriptionTerminated() {
  return getLog(redfish::registries::base::Index::subscriptionTerminated, {});
}

void subscriptionTerminated(crow::Response& res) {
  res.result(boost::beast::http::status::ok);
  addMessageToJsonRoot(res.jsonValue, subscriptionTerminated());
}

/**
 * @internal
 * @brief Formats ResourceTypeIncompatible message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resourceTypeIncompatible(std::string_view arg1,
                                        std::string_view arg2) {
  return getLog(redfish::registries::base::Index::resourceTypeIncompatible,
                std::to_array({arg1, arg2}));
}

void resourceTypeIncompatible(crow::Response& res, std::string_view arg1,
                              std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, resourceTypeIncompatible(arg1, arg2));
}

/**
 * @internal
 * @brief Formats ResetRequired message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resetRequired(boost::urls::url_view arg1,  // NOLINT
                             std::string_view arg2)       // NOLINT
{
  return getLog(redfish::registries::base::Index::resetRequired,
                std::to_array<std::string_view>({arg1.buffer(), arg2}));
}

void resetRequired(crow::Response& res, boost::urls::url_view arg1,  // NOLINT
                   std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, resetRequired(arg1, arg2));
}

/**
 * @internal
 * @brief Formats ChassisPowerStateOnRequired message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json chassisPowerStateOnRequired(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::resetRequired,
                std::to_array({arg1}));
}

void chassisPowerStateOnRequired(crow::Response& res, std::string_view arg1) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, chassisPowerStateOnRequired(arg1));
}

/**
 * @internal
 * @brief Formats ChassisPowerStateOffRequired message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json chassisPowerStateOffRequired(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::chassisPowerStateOffRequired,
                std::to_array({arg1}));
}

void chassisPowerStateOffRequired(crow::Response& res, std::string_view arg1) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, chassisPowerStateOffRequired(arg1));
}

/**
 * @internal
 * @brief Formats PropertyValueConflict message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyValueConflict(std::string_view arg1,
                                     std::string_view arg2) {
  return getLog(redfish::registries::base::Index::propertyValueConflict,
                std::to_array({arg1, arg2}));
}

void propertyValueConflict(crow::Response& res, std::string_view arg1,
                           std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, propertyValueConflict(arg1, arg2));
}

/**
 * @internal
 * @brief Formats PropertyValueResourceConflict message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyValueResourceConflict(
    std::string_view arg1, std::string_view arg2,
    boost::urls::url_view arg3)  // NOLINT
{
  return getLog(redfish::registries::base::Index::propertyValueResourceConflict,
                std::to_array<std::string_view>({arg1, arg2, arg3.buffer()}));
}

void propertyValueResourceConflict(crow::Response& res, std::string_view arg1,
                                   std::string_view arg2,
                                   boost::urls::url_view arg3)  // NOLINT
{
  res.result(boost::beast::http::status::conflict);
  addMessageToErrorJson(res.jsonValue,
                        propertyValueResourceConflict(arg1, arg2, arg3));
}

/**
 * @internal
 * @brief Formats PropertyValueExternalConflict message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyValueExternalConflict(std::string_view arg1,
                                             std::string_view arg2) {
  return getLog(redfish::registries::base::Index::propertyValueExternalConflict,
                std::to_array({arg1, arg2}));
}

void propertyValueExternalConflict(crow::Response& res, std::string_view arg1,
                                   std::string_view arg2) {
  res.result(boost::beast::http::status::conflict);
  addMessageToErrorJson(res.jsonValue,
                        propertyValueExternalConflict(arg1, arg2));
}

/**
 * @internal
 * @brief Formats PropertyValueIncorrect message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyValueIncorrect(std::string_view arg1,
                                      std::string_view arg2) {
  return getLog(redfish::registries::base::Index::propertyValueIncorrect,
                std::to_array({arg1, arg2}));
}

void propertyValueIncorrect(crow::Response& res, std::string_view arg1,
                            std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, propertyValueIncorrect(arg1, arg2));
}

/**
 * @internal
 * @brief Formats ResourceCreationConflict message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resourceCreationConflict(boost::urls::url_view arg1)  // NOLINT
{
  return getLog(redfish::registries::base::Index::resourceCreationConflict,
                std::to_array<std::string_view>({arg1.buffer()}));
}

void resourceCreationConflict(crow::Response& res,
                              boost::urls::url_view arg1)  // NOLINT
{
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, resourceCreationConflict(arg1));
}

/**
 * @internal
 * @brief Formats MaximumErrorsExceeded message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json maximumErrorsExceeded() {
  return getLog(redfish::registries::base::Index::maximumErrorsExceeded, {});
}

void maximumErrorsExceeded(crow::Response& res) {
  res.result(boost::beast::http::status::internal_server_error);
  addMessageToErrorJson(res.jsonValue, maximumErrorsExceeded());
}

/**
 * @internal
 * @brief Formats PreconditionFailed message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json preconditionFailed() {
  return getLog(redfish::registries::base::Index::preconditionFailed, {});
}

void preconditionFailed(crow::Response& res) {
  res.result(boost::beast::http::status::precondition_failed);
  addMessageToErrorJson(res.jsonValue, preconditionFailed());
}

/**
 * @internal
 * @brief Formats PreconditionRequired message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json preconditionRequired() {
  return getLog(redfish::registries::base::Index::preconditionRequired, {});
}

void preconditionRequired(crow::Response& res) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, preconditionRequired());
}

/**
 * @internal
 * @brief Formats OperationFailed message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json operationFailed() {
  return getLog(redfish::registries::base::Index::operationFailed, {});
}

void operationFailed(crow::Response& res) {
  res.result(boost::beast::http::status::bad_gateway);
  addMessageToErrorJson(res.jsonValue, operationFailed());
}

/**
 * @internal
 * @brief Formats OperationTimeout message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json operationTimeout() {
  return getLog(redfish::registries::base::Index::operationTimeout, {});
}

void operationTimeout(crow::Response& res) {
  res.result(boost::beast::http::status::internal_server_error);
  addMessageToErrorJson(res.jsonValue, operationTimeout());
}

/**
 * @internal
 * @brief Formats PropertyValueTypeError message into JSON for the specified
 * property
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyValueTypeError(std::string_view arg1,
                                      std::string_view arg2) {
  return getLog(redfish::registries::base::Index::propertyValueTypeError,
                std::to_array({arg1, arg2}));
}

void propertyValueTypeError(crow::Response& res, std::string_view arg1,
                            std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToJson(res.jsonValue, propertyValueTypeError(arg1, arg2), arg2);
}

/**
 * @internal
 * @brief Formats ResourceNotFound message into JSONd
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resourceNotFound(std::string_view arg1, std::string_view arg2) {
  return getLog(redfish::registries::base::Index::resourceNotFound,
                std::to_array({arg1, arg2}));
}

void resourceNotFound(crow::Response& res, std::string_view arg1,
                      std::string_view arg2) {
  res.result(boost::beast::http::status::not_found);
  addMessageToErrorJson(res.jsonValue, resourceNotFound(arg1, arg2));
}

/**
 * @internal
 * @brief Formats CouldNotEstablishConnection message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json couldNotEstablishConnection(
    boost::urls::url_view arg1)  // NOLINT
{
  return getLog(redfish::registries::base::Index::couldNotEstablishConnection,
                std::to_array<std::string_view>({arg1.buffer()}));
}

void couldNotEstablishConnection(crow::Response& res,
                                 boost::urls::url_view arg1)  // NOLINT
{
  res.result(boost::beast::http::status::not_found);
  addMessageToErrorJson(res.jsonValue, couldNotEstablishConnection(arg1));
}

/**
 * @internal
 * @brief Formats PropertyNotWritable message into JSON for the specified
 * property
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyNotWritable(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::propertyNotWritable,
                std::to_array({arg1}));
}

void propertyNotWritable(crow::Response& res, std::string_view arg1) {
  res.result(boost::beast::http::status::forbidden);
  addMessageToJson(res.jsonValue, propertyNotWritable(arg1), arg1);
}

/**
 * @internal
 * @brief Formats QueryParameterValueTypeError message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json queryParameterValueTypeError(std::string_view arg1,
                                            std::string_view arg2) {
  return getLog(redfish::registries::base::Index::queryParameterValueTypeError,
                std::to_array({arg1, arg2}));
}

void queryParameterValueTypeError(crow::Response& res, std::string_view arg1,
                                  std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue,
                        queryParameterValueTypeError(arg1, arg2));
}

/**
 * @internal
 * @brief Formats ServiceShuttingDown message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json serviceShuttingDown() {
  return getLog(redfish::registries::base::Index::serviceShuttingDown, {});
}

void serviceShuttingDown(crow::Response& res) {
  res.result(boost::beast::http::status::service_unavailable);
  addMessageToErrorJson(res.jsonValue, serviceShuttingDown());
}

/**
 * @internal
 * @brief Formats ActionParameterDuplicate message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json actionParameterDuplicate(std::string_view arg1,
                                        std::string_view arg2) {
  return getLog(redfish::registries::base::Index::actionParameterDuplicate,
                std::to_array({arg1, arg2}));
}

void actionParameterDuplicate(crow::Response& res, std::string_view arg1,
                              std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, actionParameterDuplicate(arg1, arg2));
}

/**
 * @internal
 * @brief Formats ActionParameterNotSupported message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json actionParameterNotSupported(std::string_view arg1,
                                           std::string_view arg2) {
  return getLog(redfish::registries::base::Index::actionParameterNotSupported,
                std::to_array({arg1, arg2}));
}

void actionParameterNotSupported(crow::Response& res, std::string_view arg1,
                                 std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, actionParameterNotSupported(arg1, arg2));
}

/**
 * @internal
 * @brief Formats SourceDoesNotSupportProtocol message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json sourceDoesNotSupportProtocol(
    boost::urls::url_view arg1,  // NOLINT
    std::string_view arg2) {
  return getLog(redfish::registries::base::Index::sourceDoesNotSupportProtocol,
                std::to_array<std::string_view>({arg1.buffer(), arg2}));
}

void sourceDoesNotSupportProtocol(crow::Response& res,
                                  boost::urls::url_view arg1,  // NOLINT
                                  std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue,
                        sourceDoesNotSupportProtocol(arg1, arg2));
}

/**
 * @internal
 * @brief Formats StrictAccountTypes message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json strictAccountTypes(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::strictAccountTypes,
                std::to_array({arg1}));
}

void strictAccountTypes(crow::Response& res, std::string_view arg1) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, strictAccountTypes(arg1));
}

/**
 * @internal
 * @brief Formats AccountRemoved message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json accountRemoved() {
  return getLog(redfish::registries::base::Index::accountRemoved, {});
}

void accountRemoved(crow::Response& res) {
  res.result(boost::beast::http::status::ok);
  addMessageToJsonRoot(res.jsonValue, accountRemoved());
}

/**
 * @internal
 * @brief Formats AccessDenied message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json accessDenied(boost::urls::url_view arg1)  // NOLINT
{
  return getLog(redfish::registries::base::Index::accessDenied,
                std::to_array<std::string_view>({arg1.buffer()}));
}

void accessDenied(crow::Response& res, boost::urls::url_view arg1)  // NOLINT
{
  res.result(boost::beast::http::status::forbidden);
  addMessageToErrorJson(res.jsonValue, accessDenied(arg1));
}

/**
 * @internal
 * @brief Formats QueryNotSupported message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json queryNotSupported() {
  return getLog(redfish::registries::base::Index::queryNotSupported, {});
}

void queryNotSupported(crow::Response& res) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, queryNotSupported());
}

/**
 * @internal
 * @brief Formats CreateLimitReachedForResource message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json createLimitReachedForResource() {
  return getLog(redfish::registries::base::Index::createLimitReachedForResource,
                {});
}

void createLimitReachedForResource(crow::Response& res) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, createLimitReachedForResource());
}

/**
 * @internal
 * @brief Formats GeneralError message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json generalError() {
  return getLog(redfish::registries::base::Index::generalError, {});
}

void generalError(crow::Response& res) {
  res.result(boost::beast::http::status::internal_server_error);
  addMessageToErrorJson(res.jsonValue, generalError());
}

/**
 * @internal
 * @brief Formats Success message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json success() {
  return getLog(redfish::registries::base::Index::success, {});
}

void success(crow::Response& res) {
  // don't set res.result here because success is the default and any
  // error should overwrite the default
  addMessageToJsonRoot(res.jsonValue, success());
}

/**
 * @internal
 * @brief Formats Created message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json created() {
  return getLog(redfish::registries::base::Index::created, {});
}

void created(crow::Response& res) {
  res.result(boost::beast::http::status::created);
  addMessageToJsonRoot(res.jsonValue, created());
}

/**
 * @internal
 * @brief Formats NoOperation message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json noOperation() {
  return getLog(redfish::registries::base::Index::noOperation, {});
}

void noOperation(crow::Response& res) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, noOperation());
}

/**
 * @internal
 * @brief Formats PropertyUnknown message into JSON for the specified
 * property
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyUnknown(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::propertyUnknown,
                std::to_array({arg1}));
}

void propertyUnknown(crow::Response& res, std::string_view arg1) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, propertyUnknown(arg1));
}

/**
 * @internal
 * @brief Formats NoValidSession message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json noValidSession() {
  return getLog(redfish::registries::base::Index::noValidSession, {});
}

void noValidSession(crow::Response& res) {
  res.result(boost::beast::http::status::forbidden);
  addMessageToErrorJson(res.jsonValue, noValidSession());
}

/**
 * @internal
 * @brief Formats InvalidObject message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json invalidObject(boost::urls::url_view arg1)  // NOLINT
{
  return getLog(redfish::registries::base::Index::invalidObject,
                std::to_array<std::string_view>({arg1.buffer()}));
}

void invalidObject(crow::Response& res, boost::urls::url_view arg1)  // NOLINT
{
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, invalidObject(arg1));
}

/**
 * @internal
 * @brief Formats InvalidURI message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json invalidURI(boost::urls::url_view arg1)  // NOLINT
{
  return getLog(redfish::registries::base::Index::invalidURI,
                std::to_array<std::string_view>({arg1.buffer()}));
}

void invalidURI(crow::Response& res, boost::urls::url_view arg1)  // NOLINT
{
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, invalidURI(arg1));
}

/**
 * @internal
 * @brief Formats ResourceInStandby message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resourceInStandby() {
  return getLog(redfish::registries::base::Index::resourceInStandby, {});
}

void resourceInStandby(crow::Response& res) {
  res.result(boost::beast::http::status::service_unavailable);
  addMessageToErrorJson(res.jsonValue, resourceInStandby());
}

/**
 * @internal
 * @brief Formats ActionParameterValueTypeError message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json actionParameterValueTypeError(std::string_view arg1,
                                             std::string_view arg2,
                                             std::string_view arg3) {
  return getLog(redfish::registries::base::Index::actionParameterValueTypeError,
                std::to_array({arg1, arg2, arg3}));
}

void actionParameterValueTypeError(crow::Response& res, std::string_view arg1,
                                   std::string_view arg2,
                                   std::string_view arg3) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue,
                        actionParameterValueTypeError(arg1, arg2, arg3));
}

/**
 * @internal
 * @brief Formats SessionLimitExceeded message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json sessionLimitExceeded() {
  return getLog(redfish::registries::base::Index::sessionLimitExceeded, {});
}

void sessionLimitExceeded(crow::Response& res) {
  res.result(boost::beast::http::status::service_unavailable);
  addMessageToErrorJson(res.jsonValue, sessionLimitExceeded());
}

/**
 * @internal
 * @brief Formats ActionNotSupported message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json actionNotSupported(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::actionNotSupported,
                std::to_array({arg1}));
}

void actionNotSupported(crow::Response& res, std::string_view arg1) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, actionNotSupported(arg1));
}

/**
 * @internal
 * @brief Formats InvalidIndex message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json invalidIndex(int64_t arg1) {
  std::string arg1_str = std::to_string(arg1);
  return getLog(redfish::registries::base::Index::invalidIndex,
                std::to_array<std::string_view>({arg1_str}));
}

void invalidIndex(crow::Response& res, int64_t arg1) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, invalidIndex(arg1));
}

/**
 * @internal
 * @brief Formats EmptyJSON message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json emptyJSON() {
  return getLog(redfish::registries::base::Index::emptyJSON, {});
}

void emptyJSON(crow::Response& res) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, emptyJSON());
}

/**
 * @internal
 * @brief Formats QueryNotSupportedOnResource message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json queryNotSupportedOnResource() {
  return getLog(redfish::registries::base::Index::queryNotSupportedOnResource,
                {});
}

void queryNotSupportedOnResource(crow::Response& res) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, queryNotSupportedOnResource());
}

/**
 * @internal
 * @brief Formats QueryNotSupportedOnOperation message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json queryNotSupportedOnOperation() {
  return getLog(redfish::registries::base::Index::queryNotSupportedOnOperation,
                {});
}

void queryNotSupportedOnOperation(crow::Response& res) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, queryNotSupportedOnOperation());
}

/**
 * @internal
 * @brief Formats QueryCombinationInvalid message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json queryCombinationInvalid() {
  return getLog(redfish::registries::base::Index::queryCombinationInvalid, {});
}

void queryCombinationInvalid(crow::Response& res) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, queryCombinationInvalid());
}

/**
 * @internal
 * @brief Formats InsufficientPrivilege message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json insufficientPrivilege() {
  return getLog(redfish::registries::base::Index::insufficientPrivilege, {});
}

void insufficientPrivilege(crow::Response& res) {
  res.result(boost::beast::http::status::forbidden);
  addMessageToErrorJson(res.jsonValue, insufficientPrivilege());
}

/**
 * @internal
 * @brief Formats PropertyValueModified message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyValueModified(std::string_view arg1,
                                     std::string_view arg2) {
  return getLog(redfish::registries::base::Index::propertyValueModified,
                std::to_array({arg1, arg2}));
}

void propertyValueModified(crow::Response& res, std::string_view arg1,
                           std::string_view arg2) {
  res.result(boost::beast::http::status::ok);
  addMessageToJson(res.jsonValue, propertyValueModified(arg1, arg2), arg1);
}

/**
 * @internal
 * @brief Formats AccountNotModified message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json accountNotModified() {
  return getLog(redfish::registries::base::Index::accountNotModified, {});
}

void accountNotModified(crow::Response& res) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, accountNotModified());
}

/**
 * @internal
 * @brief Formats QueryParameterValueFormatError message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json queryParameterValueFormatError(std::string_view arg1,
                                              std::string_view arg2) {
  return getLog(
      redfish::registries::base::Index::queryParameterValueFormatError,
      std::to_array({arg1, arg2}));
}

void queryParameterValueFormatError(crow::Response& res, std::string_view arg1,
                                    std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue,
                        queryParameterValueFormatError(arg1, arg2));
}

/**
 * @internal
 * @brief Formats PropertyMissing message into JSON for the specified
 * property
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json propertyMissing(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::propertyMissing,
                std::to_array({arg1}));
}

void propertyMissing(crow::Response& res, std::string_view arg1) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToJson(res.jsonValue, propertyMissing(arg1), arg1);
}

/**
 * @internal
 * @brief Formats ResourceExhaustion message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json resourceExhaustion(std::string_view arg1) {
  return getLog(redfish::registries::base::Index::resourceExhaustion,
                std::to_array({arg1}));
}

void resourceExhaustion(crow::Response& res, std::string_view arg1) {
  res.result(boost::beast::http::status::service_unavailable);
  addMessageToErrorJson(res.jsonValue, resourceExhaustion(arg1));
}

/**
 * @internal
 * @brief Formats AccountModified message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json accountModified() {
  return getLog(redfish::registries::base::Index::accountModified, {});
}

void accountModified(crow::Response& res) {
  res.result(boost::beast::http::status::ok);
  addMessageToErrorJson(res.jsonValue, accountModified());
}

/**
 * @internal
 * @brief Formats QueryParameterOutOfRange message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json queryParameterOutOfRange(std::string_view arg1,
                                        std::string_view arg2,
                                        std::string_view arg3) {
  return getLog(redfish::registries::base::Index::queryParameterOutOfRange,
                std::to_array({arg1, arg2, arg3}));
}

void queryParameterOutOfRange(crow::Response& res, std::string_view arg1,
                              std::string_view arg2, std::string_view arg3) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue,
                        queryParameterOutOfRange(arg1, arg2, arg3));
}

nlohmann::json passwordChangeRequired(boost::urls::url_view arg1)  // NOLINT
{
  return getLog(redfish::registries::base::Index::passwordChangeRequired,
                std::to_array<std::string_view>({arg1.buffer()}));
}

/**
 * @internal
 * @brief Formats PasswordChangeRequired message into JSON
 *
 * See header file for more information
 * @endinternal
 */
void passwordChangeRequired(crow::Response& res,
                            boost::urls::url_view arg1)  // NOLINT
{
  messages::addMessageToJsonRoot(res.jsonValue, passwordChangeRequired(arg1));
}

/**
 * @internal
 * @brief Formats InsufficientStorage message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json insufficientStorage() {
  return getLog(redfish::registries::base::Index::insufficientStorage, {});
}

void insufficientStorage(crow::Response& res) {
  res.result(boost::beast::http::status::insufficient_storage);
  addMessageToErrorJson(res.jsonValue, insufficientStorage());
}

/**
 * @internal
 * @brief Formats OperationNotAllowed message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json operationNotAllowed() {
  return getLog(redfish::registries::base::Index::operationNotAllowed, {});
}

void operationNotAllowed(crow::Response& res) {
  res.result(boost::beast::http::status::method_not_allowed);
  addMessageToErrorJson(res.jsonValue, operationNotAllowed());
}

void invalidUpload(crow::Response& res, std::string_view arg1,
                   std::string_view arg2) {
  res.result(boost::beast::http::status::bad_request);
  addMessageToErrorJson(res.jsonValue, invalidUpload(arg1, arg2));
}

/**
 * @internal
 * @brief Formats Invalid File message into JSON
 *
 * See header file for more information
 * @endinternal
 */
nlohmann::json invalidUpload(std::string_view arg1, std::string_view arg2) {
  std::string msg = "Invalid file uploaded to ";
  msg += arg1;
  msg += ": ";
  msg += arg2;
  msg += ".";

  nlohmann::json::object_t ret;
  ret["@odata.type"] = "/redfish/v1/$metadata#Message.v1_1_1.Message";
  ret["MessageId"] = "OpenBMC.0.2.InvalidUpload";
  ret["Message"] = std::move(msg);
  nlohmann::json::array_t args;
  args.emplace_back(arg1);
  args.emplace_back(arg2);
  ret["MessageArgs"] = std::move(args);
  ret["MessageSeverity"] = "Warning";
  ret["Resolution"] = "None.";
  return ret;
}

}  // namespace messages

}  // namespace redfish
