/**
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *
 *    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 "software-diagnostics-server.h"
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/AttributeAccessInterface.h>
#include <app/CommandHandler.h>
#include <app/CommandHandlerInterface.h>
#include <app/ConcreteCommandPath.h>
#include <app/EventLogging.h>
#include <app/InteractionModelEngine.h>
#include <app/util/attribute-storage.h>
#include <lib/core/Optional.h>
#include <platform/DiagnosticDataProvider.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::SoftwareDiagnostics;
using namespace chip::app::Clusters::SoftwareDiagnostics::Attributes;
using chip::DeviceLayer::DiagnosticDataProvider;
using chip::DeviceLayer::GetDiagnosticDataProvider;

namespace {

class SoftwareDiagosticsAttrAccess : public AttributeAccessInterface
{
public:
    // Register for the SoftwareDiagnostics cluster on all endpoints.
    SoftwareDiagosticsAttrAccess() : AttributeAccessInterface(Optional<EndpointId>::Missing(), SoftwareDiagnostics::Id) {}

    CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;

private:
    CHIP_ERROR ReadIfSupported(CHIP_ERROR (DiagnosticDataProvider::*getter)(uint64_t &), AttributeValueEncoder & aEncoder);
    CHIP_ERROR ReadThreadMetrics(AttributeValueEncoder & aEncoder);
};

class SoftwareDiagnosticsCommandHandler : public CommandHandlerInterface
{
public:
    // Register for the SoftwareDiagnostics cluster on all endpoints.
    SoftwareDiagnosticsCommandHandler() : CommandHandlerInterface(Optional<EndpointId>::Missing(), SoftwareDiagnostics::Id) {}

    void InvokeCommand(HandlerContext & handlerContext) override;

    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override;
};

SoftwareDiagosticsAttrAccess gAttrAccess;

SoftwareDiagnosticsCommandHandler gCommandHandler;

CHIP_ERROR SoftwareDiagosticsAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
    if (aPath.mClusterId != SoftwareDiagnostics::Id)
    {
        // We shouldn't have been called at all.
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    switch (aPath.mAttributeId)
    {
    case CurrentHeapFree::Id:
        return ReadIfSupported(&DiagnosticDataProvider::GetCurrentHeapFree, aEncoder);
    case CurrentHeapUsed::Id:
        return ReadIfSupported(&DiagnosticDataProvider::GetCurrentHeapUsed, aEncoder);
    case CurrentHeapHighWatermark::Id:
        return ReadIfSupported(&DiagnosticDataProvider::GetCurrentHeapHighWatermark, aEncoder);
    case ThreadMetrics::Id:
        return ReadThreadMetrics(aEncoder);
    case Clusters::Globals::Attributes::FeatureMap::Id: {
        BitFlags<Feature> features;

        if (DeviceLayer::GetDiagnosticDataProvider().SupportsWatermarks())
        {
            features.Set(Feature::kWatermarks);
        }

        return aEncoder.Encode(features);
    }
    default:
        break;
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR SoftwareDiagosticsAttrAccess::ReadIfSupported(CHIP_ERROR (DiagnosticDataProvider::*getter)(uint64_t &),
                                                         AttributeValueEncoder & aEncoder)
{
    uint64_t data;
    CHIP_ERROR err = (DeviceLayer::GetDiagnosticDataProvider().*getter)(data);
    if (err == CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE)
    {
        data = 0;
    }
    else if (err != CHIP_NO_ERROR)
    {
        return err;
    }

    return aEncoder.Encode(data);
}

CHIP_ERROR SoftwareDiagosticsAttrAccess::ReadThreadMetrics(AttributeValueEncoder & aEncoder)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    DeviceLayer::ThreadMetrics * threadMetrics;

    if (DeviceLayer::GetDiagnosticDataProvider().GetThreadMetrics(&threadMetrics) == CHIP_NO_ERROR)
    {
        err = aEncoder.EncodeList([&threadMetrics](const auto & encoder) -> CHIP_ERROR {
            for (DeviceLayer::ThreadMetrics * thread = threadMetrics; thread != nullptr; thread = thread->Next)
            {
                ReturnErrorOnFailure(encoder.Encode(*thread));
            }

            return CHIP_NO_ERROR;
        });

        DeviceLayer::GetDiagnosticDataProvider().ReleaseThreadMetrics(threadMetrics);
    }
    else
    {
        err = aEncoder.EncodeEmptyList();
    }

    return err;
}

void SoftwareDiagnosticsCommandHandler::InvokeCommand(HandlerContext & handlerContext)
{
    using Protocols::InteractionModel::Status;
    if (handlerContext.mRequestPath.mCommandId != Commands::ResetWatermarks::Id)
    {
        // Normal error handling
        return;
    }

    handlerContext.SetCommandHandled();
    Status status = Status::Success;
    if (!DeviceLayer::GetDiagnosticDataProvider().SupportsWatermarks())
    {
        status = Status::UnsupportedCommand;
    }
    else if (DeviceLayer::GetDiagnosticDataProvider().ResetWatermarks() != CHIP_NO_ERROR)
    {
        status = Status::Failure;
    }
    handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
}

CHIP_ERROR SoftwareDiagnosticsCommandHandler::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
                                                                        CommandIdCallback callback, void * context)
{
    if (!DeviceLayer::GetDiagnosticDataProvider().SupportsWatermarks())
    {
        // No commmands.
        return CHIP_NO_ERROR;
    }

    callback(Commands::ResetWatermarks::Id, context);

    return CHIP_NO_ERROR;
}

} // anonymous namespace

namespace chip {
namespace app {
namespace Clusters {

SoftwareDiagnosticsServer SoftwareDiagnosticsServer::instance;

/**********************************************************
 * SoftwareDiagnosticsServer Implementation
 *********************************************************/

SoftwareDiagnosticsServer & SoftwareDiagnosticsServer::Instance()
{
    return instance;
}

// Gets called when a software fault that has taken place on the Node.
void SoftwareDiagnosticsServer::OnSoftwareFaultDetect(const SoftwareDiagnostics::Events::SoftwareFault::Type & softwareFault)
{
    ChipLogDetail(Zcl, "SoftwareDiagnosticsDelegate: OnSoftwareFaultDetected");

    for (auto endpoint : EnabledEndpointsWithServerCluster(SoftwareDiagnostics::Id))
    {
        // If Software Diagnostics cluster is implemented on this endpoint
        EventNumber eventNumber;

        if (CHIP_NO_ERROR != LogEvent(softwareFault, endpoint, eventNumber))
        {
            ChipLogError(Zcl, "SoftwareDiagnosticsDelegate: Failed to record SoftwareFault event");
        }
    }
}

} // namespace Clusters
} // namespace app
} // namespace chip

bool emberAfSoftwareDiagnosticsClusterResetWatermarksCallback(app::CommandHandler * commandObj,
                                                              const app::ConcreteCommandPath & commandPath,
                                                              const Commands::ResetWatermarks::DecodableType & commandData)
{
    // Shouldn't be called at all.
    return false;
}

void MatterSoftwareDiagnosticsPluginServerInitCallback()
{
    registerAttributeAccessOverride(&gAttrAccess);
    InteractionModelEngine::GetInstance()->RegisterCommandHandler(&gCommandHandler);
}
