/*
 *   Copyright (c) 2022 Project CHIP Authors
 *   All rights reserved.
 *
 *   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 "Log.h"

#include "ToCertificateString.h"

#include <lib/support/BytesToHex.h>
#include <lib/support/SafeInt.h>

namespace chip {
namespace trace {
namespace logging {

namespace {

constexpr uint8_t kSpacePerIndent = 4;
uint8_t gIndentLevel              = 0;

void ENFORCE_FORMAT(1, 2) LogFormatted(const char * format, ...)
{
    char buffer[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE] = {};

    int indentation = gIndentLevel * kSpacePerIndent;
    snprintf(buffer, sizeof(buffer), "%*s", indentation, "");

    va_list args;
    va_start(args, format);
    vsnprintf(&buffer[indentation], sizeof(buffer) - static_cast<size_t>(indentation), format, args);
    va_end(args);

    ChipLogDetail(DataManagement, "%s", buffer);
}

const char * ToHexString(chip::ByteSpan source, MutableCharSpan destination)
{
    memset(destination.data(), '\0', destination.size());

    if (source.size() == 0)
    {
        return destination.data();
    }

    CHIP_ERROR err =
        Encoding::BytesToHex(source.data(), source.size(), destination.data(), destination.size(), Encoding::HexFlags::kUppercase);
    if (CHIP_NO_ERROR != err)
    {
        LogErrorOnFailure(err);
        return destination.data();
    }

    return destination.data();
}

} // namespace

void Log(const char * name, ByteSpan & data)
{
    if (data.empty())
    {
        return;
    }

    char buffer[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE];
    chip::MutableCharSpan destination(buffer);

    CanCastTo<uint16_t>(data.size())
        ? LogFormatted("%s (%u) = %s", name, static_cast<uint16_t>(data.size()), ToHexString(data, destination))
        : LogFormatted("%s (>UINT16_MAX) = %s", name, ToHexString(data, destination));
}

void Log(const char * name, CharSpan & data)
{
    if (data.empty())
    {
        return;
    }

    CanCastTo<uint16_t>(data.size())
        ? LogFormatted("%s (%u) = %.*s", name, static_cast<uint16_t>(data.size()), static_cast<int>(data.size()), data.data())
        : LogFormatted("%s (>UINT16_MAX) = %.*s", name, static_cast<int>(data.size()), data.data());
}

void Log(const char * name, uint16_t value)
{
    LogFormatted("%s = %u", name, value);
}

void Log(const char * name, uint32_t value)
{
    LogFormatted("%s = %u", name, value);
}

void Log(const char * name, const char * value)
{
    LogFormatted("%s = %s", name, value);
}

void Log(const char * name)
{
    LogFormatted("%s", name);
}

void LogAsHex(const char * name, uint16_t value)
{
    LogFormatted("%s = 0x%04x", name, value);
}

void LogAsHex(const char * name, uint64_t value)
{
    LogFormatted("%s = " ChipLogFormatX64, name, ChipLogValueX64(value));
}

void LogCertificate(const char * name, const ByteSpan & data)
{
    char buffer[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE] = {};
    chip::MutableCharSpan destination(buffer);

    CanCastTo<uint16_t>(data.size()) ? LogFormatted("%s (%u) =", name, static_cast<uint16_t>(data.size()))
                                     : LogFormatted("%s (>UINT16_MAX) =", name);
    LogFormatted("{\n%s", ToCertificateString(data, destination));
    LogFormatted("}");
    LogFormatted(" ");
}

void LogCertificateRequest(const char * name, const ByteSpan & data)
{
    char buffer[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE] = {};
    chip::MutableCharSpan destination(buffer);

    CanCastTo<uint16_t>(data.size()) ? LogFormatted("%s (%u) =", name, static_cast<uint16_t>(data.size()))
                                     : LogFormatted("%s (>UINT16_MAX) =", name);
    LogFormatted("{\n%s", ToCertificateRequestString(data, destination));
    LogFormatted("}");
    LogFormatted(" ");
}

void IncreaseLogIndent()
{
    LogFormatted("{");
    gIndentLevel++;
}

void DecreaseLogIndent()
{
    gIndentLevel--;
    LogFormatted("}");

    if (gIndentLevel == 0)
    {
        LogFormatted(" ");
    }
}

ScopedLogIndent::ScopedLogIndent(const char * name)
{
    LogFormatted("%s =", name);
    IncreaseLogIndent();
}

ScopedLogIndent::~ScopedLogIndent()
{
    DecreaseLogIndent();
}

ScopedLogIndentWithFlags::ScopedLogIndentWithFlags(const char * name, uint8_t flags)
{
    LogFormatted("%s (0x%02x) =", name, flags);
    IncreaseLogIndent();
}

ScopedLogIndentWithFlags::~ScopedLogIndentWithFlags()
{
    DecreaseLogIndent();
}

ScopedLogIndentWithSize::ScopedLogIndentWithSize(const char * name, size_t size)
{
    CanCastTo<uint16_t>(size) ? LogFormatted("%s (%u bytes) =", name, static_cast<uint16_t>(size))
                              : LogFormatted("%s (>UINT16_MAX) =", name);
    IncreaseLogIndent();
}

ScopedLogIndentWithSize::~ScopedLogIndentWithSize()
{
    DecreaseLogIndent();
}

} // namespace logging
} // namespace trace
} // namespace chip
