/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *
 *    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 <lib/core/ErrorStr.h>

#include <lib/core/CHIPConfig.h>
#include <lib/core/CHIPError.h>
#include <lib/support/DLLUtil.h>

#include <inttypes.h>
#include <stdio.h>

namespace chip {

/**
 * Static buffer to store the formatted error string.
 */
static char sErrorStr[CHIP_CONFIG_ERROR_STR_SIZE];

/**
 * Linked-list of error formatter functions.
 */
static ErrorFormatter * sErrorFormatterList = nullptr;

/**
 * This routine returns a human-readable NULL-terminated C string
 * describing the provided error.
 *
 * @param[in] err                      The error for format and describe.
 *
 * @return A pointer to a NULL-terminated C string describing the
 *         provided error.
 */
DLL_EXPORT const char * ErrorStr(CHIP_ERROR err)
{
    char * formattedError   = sErrorStr;
    uint16_t formattedSpace = sizeof(sErrorStr);

#if CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR

    const char * const file = err.GetFile();
    if (file != nullptr)
    {
        int n = snprintf(formattedError, formattedSpace, "%s:%u: ", file, err.GetLine());
        if (n > formattedSpace)
        {
            n = formattedSpace;
        }
        formattedError += n;
        formattedSpace = static_cast<uint16_t>(formattedSpace - n);
    }
    if (err == CHIP_NO_ERROR)
    {
        (void) snprintf(formattedError, formattedSpace, CHIP_NO_ERROR_STRING);
        return sErrorStr;
    }

#else // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR

    if (err == CHIP_NO_ERROR)
    {
        return CHIP_NO_ERROR_STRING;
    }

#endif // CHIP_CONFIG_ERROR_SOURCE && !CHIP_CONFIG_SHORT_ERROR_STR

    // Search the registered error formatter for one that will format the given
    // error code.
    for (const ErrorFormatter * errFormatter = sErrorFormatterList; errFormatter != nullptr; errFormatter = errFormatter->Next)
    {
        if (errFormatter->FormatError(formattedError, formattedSpace, err))
        {
            return sErrorStr;
        }
    }

    // Use a default formatting if no formatter found.
    FormatError(formattedError, formattedSpace, nullptr, err, nullptr);
    return sErrorStr;
}

/**
 * Add a new error formatter function to the global list of error formatters.
 *
 * @param[in] errFormatter             An ErrorFormatter structure containing a
 *                                     pointer to the new error function.  Note
 *                                     that a pointer to the supplied ErrorFormatter
 *                                     structure will be retained by the function.
 *                                     Thus the memory for the structure must
 *                                     remain reserved.
 */
DLL_EXPORT void RegisterErrorFormatter(ErrorFormatter * errFormatter)
{
    // Do nothing if a formatter with the same format function is already in the list.
    for (ErrorFormatter * existingFormatter = sErrorFormatterList; existingFormatter != nullptr;
         existingFormatter                  = existingFormatter->Next)
    {
        if (existingFormatter->FormatError == errFormatter->FormatError)
        {
            return;
        }
    }

    // Add the formatter to the global list.
    errFormatter->Next  = sErrorFormatterList;
    sErrorFormatterList = errFormatter;
}

/**
 * Remove an error formatter function from the global list of error formatters.
 *
 * @param[in] errFormatter             An ErrorFormatter structure containing a
 *                                     pointer to the new error function.
 */
DLL_EXPORT void DeregisterErrorFormatter(ErrorFormatter * errFormatter)
{
    // Remove the formatter if present
    for (ErrorFormatter ** lfp = &sErrorFormatterList; *lfp != nullptr; lfp = &(*lfp)->Next)
    {
        // Remove the formatter from the global list, if found.
        if (*lfp == errFormatter)
        {
            *lfp = errFormatter->Next;
        }
    }
}

#if !CHIP_CONFIG_CUSTOM_ERROR_FORMATTER

/**
 * Generates a human-readable NULL-terminated C string describing the provided error.
 *
 * @param[in] buf                   Buffer into which the error string will be placed.
 * @param[in] bufSize               Size of the supplied buffer in bytes.
 * @param[in] subsys                A short string describing the subsystem that originated
 *                                  the error, or NULL if the origin of the error is
 *                                  unknown/unavailable.  This string should be 10
 *                                  characters or less.
 * @param[in] err                   The error to be formatted.
 * @param[in] desc                  A string describing the cause or meaning of the error,
 *                                  or NULL if no such information is available.
 */
DLL_EXPORT void FormatError(char * buf, uint16_t bufSize, const char * subsys, CHIP_ERROR err, const char * desc)
{
#if CHIP_CONFIG_SHORT_ERROR_STR

    if (subsys == nullptr)
    {
        (void) snprintf(buf, bufSize, "Error " CHIP_CONFIG_SHORT_FORM_ERROR_VALUE_FORMAT, err.AsInteger());
    }
    else
    {
        (void) snprintf(buf, bufSize, "Error %s:" CHIP_CONFIG_SHORT_FORM_ERROR_VALUE_FORMAT, subsys, err.AsInteger());
    }

#else // CHIP_CONFIG_SHORT_ERROR_STR

    const char * subsysSep = " ";
    const char * descSep   = ": ";

    if (subsys == nullptr)
    {
        subsys    = "";
        subsysSep = "";
    }
    if (desc == nullptr)
    {
        desc    = "";
        descSep = "";
    }

    (void) snprintf(buf, bufSize, "%s%sError 0x%08" PRIX32 "%s%s", subsys, subsysSep, err.AsInteger(), descSep, desc);

#endif // CHIP_CONFIG_SHORT_ERROR_STR
}

#endif // CHIP_CONFIG_CUSTOM_ERROR_FORMATTER

} // namespace chip
