/*
 *   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.
 *
 */

#pragma once

#include <string>

#include <app-common/zap-generated/cluster-objects.h>
#include <app/ConcreteAttributePath.h>
#include <app/ConcreteCommandPath.h>
#include <app/EventHeader.h>
#include <app/data-model/DecodableList.h>
#include <lib/support/BytesToHex.h>

class DataModelLogger
{
public:
    static CHIP_ERROR LogAttribute(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data);
    static CHIP_ERROR LogCommand(const chip::app::ConcreteCommandPath & path, chip::TLV::TLVReader * data);
    static CHIP_ERROR LogEvent(const chip::app::EventHeader & header, chip::TLV::TLVReader * data);

private:
    static CHIP_ERROR LogValue(const char * label, size_t indent, bool value)
    {
        DataModelLogger::LogString(label, indent, value ? "TRUE" : "FALSE");
        return CHIP_NO_ERROR;
    }

    static CHIP_ERROR LogValue(const char * label, size_t indent, chip::CharSpan value)
    {
        DataModelLogger::LogString(label, indent, std::string(value.data(), value.size()));
        return CHIP_NO_ERROR;
    }

    static CHIP_ERROR LogValue(const char * label, size_t indent, chip::ByteSpan value)
    {
        // CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE includes various prefixes we don't
        // control (timestamps, process ids, etc).  Let's assume (hope?) that
        // those prefixes use up no more than half the total available space.
        // Right now it looks like the prefixes are 45 chars out of a 255 char
        // buffer.
        char buffer[CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE / 2];
        size_t prefixSize = ComputePrefixSize(label, indent);
        if (prefixSize > ArraySize(buffer))
        {
            DataModelLogger::LogString("", 0, "Prefix is too long to fit in buffer");
            return CHIP_ERROR_INTERNAL;
        }

        const size_t availableSize = ArraySize(buffer) - prefixSize;
        // Each byte ends up as two hex characters.
        const size_t bytesPerLogCall = availableSize / 2;
        std::string labelStr(label);
        while (value.size() > bytesPerLogCall)
        {
            ReturnErrorOnFailure(
                chip::Encoding::BytesToUppercaseHexString(value.data(), bytesPerLogCall, &buffer[0], ArraySize(buffer)));
            LogString(labelStr, indent, buffer);
            value = value.SubSpan(bytesPerLogCall);
            // For the second and following lines, make it clear that they are
            // continuation lines by replacing the label with "....".
            labelStr.replace(labelStr.begin(), labelStr.end(), labelStr.size(), '.');
        }
        ReturnErrorOnFailure(chip::Encoding::BytesToUppercaseHexString(value.data(), value.size(), &buffer[0], ArraySize(buffer)));
        LogString(labelStr, indent, buffer);

        return CHIP_NO_ERROR;
    }

    template <typename X,
              typename std::enable_if_t<
                  std::is_integral<X>::value && !std::is_same<std::remove_cv_t<std::remove_reference_t<X>>, bool>::value, int> = 0>
    static CHIP_ERROR LogValue(const char * label, size_t indent, X value)
    {
        DataModelLogger::LogString(label, indent, std::to_string(value));
        return CHIP_NO_ERROR;
    }

    template <typename X, typename std::enable_if_t<std::is_floating_point<X>::value, int> = 0>
    static CHIP_ERROR LogValue(const char * label, size_t indent, X value)
    {
        DataModelLogger::LogString(label, indent, std::to_string(value));
        return CHIP_NO_ERROR;
    }

    template <typename X, typename std::enable_if_t<std::is_enum<X>::value, int> = 0>
    static CHIP_ERROR LogValue(const char * label, size_t indent, X value)
    {
        DataModelLogger::LogValue(label, indent, chip::to_underlying(value));
        return CHIP_NO_ERROR;
    }

    template <typename X>
    static CHIP_ERROR LogValue(const char * label, size_t indent, chip::BitFlags<X> value)
    {
        DataModelLogger::LogValue(label, indent, value.Raw());
        return CHIP_NO_ERROR;
    }

    template <typename T>
    static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::DataModel::DecodableList<T> & value)
    {
        size_t count   = 0;
        CHIP_ERROR err = value.ComputeSize(&count);
        if (err != CHIP_NO_ERROR)
        {
            return err;
        }
        DataModelLogger::LogString(label, indent, std::to_string(count) + " entries");

        auto iter = value.begin();
        size_t i  = 0;
        while (iter.Next())
        {
            ++i;
            std::string itemLabel = std::string("[") + std::to_string(i) + "]";
            ReturnErrorOnFailure(DataModelLogger::LogValue(itemLabel.c_str(), indent + 1, iter.GetValue()));
        }
        if (iter.GetStatus() != CHIP_NO_ERROR)
        {
            DataModelLogger::LogString(indent + 1, "List truncated due to invalid value");
        }
        return iter.GetStatus();
    }

    template <typename T>
    static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::app::DataModel::Nullable<T> & value)
    {
        if (value.IsNull())
        {
            DataModelLogger::LogString(label, indent, "null");
        }
        else
        {
            DataModelLogger::LogValue(label, indent, value.Value());
        }

        return CHIP_NO_ERROR;
    }

    template <typename T>
    static CHIP_ERROR LogValue(const char * label, size_t indent, const chip::Optional<T> & value)
    {
        if (value.HasValue())
        {
            DataModelLogger::LogValue(label, indent, value.Value());
        }

        return CHIP_NO_ERROR;
    }

#include <zap-generated/cluster/logging/DataModelLogger.h>

    static void LogString(size_t indent, const std::string string) { LogString("", indent, string); }

    static void LogString(const std::string label, size_t indent, const std::string string)
    {
        std::string prefix = ComputePrefix(label, indent);

        ChipLogProgress(chipTool, "%s%s", prefix.c_str(), string.c_str());
    }

private:
    static std::string ComputePrefix(const std::string label, size_t indent)
    {
        std::string prefix;
        for (size_t i = 0; i < indent; ++i)
        {
            prefix.append("  ");
        }
        if (label.size() > 0)
        {
            prefix.append(label);
            prefix.append(":");
        }
        prefix.append(" ");

        return prefix;
    }

    static size_t ComputePrefixSize(const std::string label, size_t indent) { return ComputePrefix(label, indent).size(); }
};
