/**
 *
 *    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 "general-diagnostics-server.h"

#include <stdint.h>
#include <string.h>

#include <app/util/config.h>

#include "app/server/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/AttributeAccessInterfaceRegistry.h>
#include <app/EventLogging.h>
#include <app/reporting/reporting.h>
#include <app/util/attribute-storage.h>
#include <lib/support/ScopedBuffer.h>
#include <platform/ConnectivityManager.h>
#include <platform/DiagnosticDataProvider.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::GeneralDiagnostics;
using namespace chip::app::Clusters::GeneralDiagnostics::Attributes;
using namespace chip::DeviceLayer;
using chip::DeviceLayer::ConnectivityMgr;
using chip::DeviceLayer::DiagnosticDataProvider;
using chip::DeviceLayer::GetDiagnosticDataProvider;
using chip::Protocols::InteractionModel::Status;

namespace {

constexpr uint8_t kCurrentClusterRevision = 2;

bool IsTestEventTriggerEnabled()
{
    auto * triggerDelegate = chip::Server::GetInstance().GetTestEventTriggerDelegate();
    if (triggerDelegate == nullptr)
    {
        return false;
    }
    uint8_t zeroByteSpanData[TestEventTriggerDelegate::kEnableKeyLength] = { 0 };
    if (triggerDelegate->DoesEnableKeyMatch(ByteSpan(zeroByteSpanData)))
    {
        return false;
    }
    return true;
}

bool IsByteSpanAllZeros(const ByteSpan & byteSpan)
{
    for (unsigned char it : byteSpan)
    {
        if (it != 0)
        {
            return false;
        }
    }
    return true;
}

void ReportAttributeOnAllEndpoints(AttributeId attribute)
{
    for (auto endpoint : EnabledEndpointsWithServerCluster(GeneralDiagnostics::Id))
    {
        MatterReportingAttributeChangeCallback(endpoint, GeneralDiagnostics::Id, attribute);
    }
}

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

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

private:
    template <typename T>
    CHIP_ERROR ReadIfSupported(CHIP_ERROR (DiagnosticDataProvider::*getter)(T &), AttributeValueEncoder & aEncoder);

    template <typename T>
    CHIP_ERROR ReadListIfSupported(CHIP_ERROR (DiagnosticDataProvider::*getter)(T &), AttributeValueEncoder & aEncoder);

    CHIP_ERROR ReadNetworkInterfaces(AttributeValueEncoder & aEncoder);
};

template <typename T>
CHIP_ERROR GeneralDiagosticsAttrAccess::ReadIfSupported(CHIP_ERROR (DiagnosticDataProvider::*getter)(T &),
                                                        AttributeValueEncoder & aEncoder)
{
    T data;
    CHIP_ERROR err = (GetDiagnosticDataProvider().*getter)(data);
    if (err == CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE)
    {
        data = {};
    }
    else if (err != CHIP_NO_ERROR)
    {
        return err;
    }

    return aEncoder.Encode(data);
}

template <typename T>
CHIP_ERROR GeneralDiagosticsAttrAccess::ReadListIfSupported(CHIP_ERROR (DiagnosticDataProvider::*getter)(T &),
                                                            AttributeValueEncoder & aEncoder)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    T faultList;

    if ((GetDiagnosticDataProvider().*getter)(faultList) == CHIP_NO_ERROR)
    {
        err = aEncoder.EncodeList([&faultList](const auto & encoder) -> CHIP_ERROR {
            for (auto fault : faultList)
            {
                ReturnErrorOnFailure(encoder.Encode(fault));
            }

            return CHIP_NO_ERROR;
        });
    }
    else
    {
        err = aEncoder.EncodeEmptyList();
    }

    return err;
}

CHIP_ERROR GeneralDiagosticsAttrAccess::ReadNetworkInterfaces(AttributeValueEncoder & aEncoder)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    DeviceLayer::NetworkInterface * netifs;

    if (DeviceLayer::GetDiagnosticDataProvider().GetNetworkInterfaces(&netifs) == CHIP_NO_ERROR)
    {
        err = aEncoder.EncodeList([&netifs](const auto & encoder) -> CHIP_ERROR {
            for (DeviceLayer::NetworkInterface * ifp = netifs; ifp != nullptr; ifp = ifp->Next)
            {
                ReturnErrorOnFailure(encoder.Encode(*ifp));
            }

            return CHIP_NO_ERROR;
        });

        DeviceLayer::GetDiagnosticDataProvider().ReleaseNetworkInterfaces(netifs);
    }
    else
    {
        err = aEncoder.EncodeEmptyList();
    }

    return err;
}

GeneralDiagosticsAttrAccess gAttrAccess;

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

    switch (aPath.mAttributeId)
    {
    case NetworkInterfaces::Id: {
        return ReadNetworkInterfaces(aEncoder);
    }
    case ActiveHardwareFaults::Id: {
        return ReadListIfSupported(&DiagnosticDataProvider::GetActiveHardwareFaults, aEncoder);
    }
    case ActiveRadioFaults::Id: {
        return ReadListIfSupported(&DiagnosticDataProvider::GetActiveRadioFaults, aEncoder);
    }
    case ActiveNetworkFaults::Id: {
        return ReadListIfSupported(&DiagnosticDataProvider::GetActiveNetworkFaults, aEncoder);
    }
    case RebootCount::Id: {
        return ReadIfSupported(&DiagnosticDataProvider::GetRebootCount, aEncoder);
    }
    case UpTime::Id: {
        System::Clock::Seconds64 system_time_seconds =
            std::chrono::duration_cast<System::Clock::Seconds64>(Server::GetInstance().TimeSinceInit());
        return aEncoder.Encode(static_cast<uint64_t>(system_time_seconds.count()));
    }
    case TotalOperationalHours::Id: {
        return ReadIfSupported(&DiagnosticDataProvider::GetTotalOperationalHours, aEncoder);
    }
    case BootReason::Id: {
        return ReadIfSupported(&DiagnosticDataProvider::GetBootReason, aEncoder);
    }
    case TestEventTriggersEnabled::Id: {
        bool isTestEventTriggersEnabled = IsTestEventTriggerEnabled();
        return aEncoder.Encode(isTestEventTriggersEnabled);
    }
        // Note: Attribute ID 0x0009 was removed (#30002).

    case FeatureMap::Id: {
        uint32_t features = 0;

#if CHIP_CONFIG_MAX_PATHS_PER_INVOKE > 1
        features |= to_underlying(Clusters::GeneralDiagnostics::Feature::kDataModelTest);
#endif // CHIP_CONFIG_MAX_PATHS_PER_INVOKE > 1

        return aEncoder.Encode(features);
    }

    case ClusterRevision::Id: {
        return aEncoder.Encode(kCurrentClusterRevision);
    }

    default:
        break;
    }
    return CHIP_NO_ERROR;
}

class GeneralDiagnosticsDelegate : public DeviceLayer::ConnectivityManagerDelegate
{
    // Gets called when any network interface on the Node is updated.
    void OnNetworkInfoChanged() override
    {
        ChipLogDetail(Zcl, "GeneralDiagnosticsDelegate: OnNetworkInfoChanged");

        ReportAttributeOnAllEndpoints(GeneralDiagnostics::Attributes::NetworkInterfaces::Id);
    }
};

GeneralDiagnosticsDelegate gDiagnosticDelegate;

} // anonymous namespace

namespace chip {
namespace app {
namespace Clusters {

GeneralDiagnosticsServer GeneralDiagnosticsServer::instance;

/**********************************************************
 * GeneralDiagnosticsServer Implementation
 *********************************************************/

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

// Gets called when the device has been rebooted.
void GeneralDiagnosticsServer::OnDeviceReboot(BootReasonEnum bootReason)
{
    ChipLogDetail(Zcl, "GeneralDiagnostics: OnDeviceReboot");

    ReportAttributeOnAllEndpoints(GeneralDiagnostics::Attributes::BootReason::Id);

    // GeneralDiagnostics cluster should exist only for endpoint 0.
    if (emberAfContainsServer(0, GeneralDiagnostics::Id))
    {
        Events::BootReason::Type event{ bootReason };
        EventNumber eventNumber;

        CHIP_ERROR err = LogEvent(event, 0, eventNumber);
        if (CHIP_NO_ERROR != err)
        {
            ChipLogError(Zcl, "GeneralDiagnostics: Failed to record BootReason event: %" CHIP_ERROR_FORMAT, err.Format());
        }
    }
}

// Get called when the Node detects a hardware fault has been raised.
void GeneralDiagnosticsServer::OnHardwareFaultsDetect(const GeneralFaults<kMaxHardwareFaults> & previous,
                                                      const GeneralFaults<kMaxHardwareFaults> & current)
{
    ChipLogDetail(Zcl, "GeneralDiagnostics: OnHardwareFaultsDetect");

    for (auto endpointId : EnabledEndpointsWithServerCluster(GeneralDiagnostics::Id))
    {
        // If General Diagnostics cluster is implemented on this endpoint
        MatterReportingAttributeChangeCallback(endpointId, GeneralDiagnostics::Id,
                                               GeneralDiagnostics::Attributes::ActiveHardwareFaults::Id);

        // Record HardwareFault event
        EventNumber eventNumber;
        DataModel::List<const HardwareFaultEnum> currentList(reinterpret_cast<const HardwareFaultEnum *>(current.data()),
                                                             current.size());
        DataModel::List<const HardwareFaultEnum> previousList(reinterpret_cast<const HardwareFaultEnum *>(previous.data()),
                                                              previous.size());
        Events::HardwareFaultChange::Type event{ currentList, previousList };

        if (CHIP_NO_ERROR != LogEvent(event, endpointId, eventNumber))
        {
            ChipLogError(Zcl, "GeneralDiagnostics: Failed to record HardwareFault event");
        }
    }
}

// Get called when the Node detects a radio fault has been raised.
void GeneralDiagnosticsServer::OnRadioFaultsDetect(const GeneralFaults<kMaxRadioFaults> & previous,
                                                   const GeneralFaults<kMaxRadioFaults> & current)
{
    ChipLogDetail(Zcl, "GeneralDiagnostics: OnRadioFaultsDetect");

    for (auto endpointId : EnabledEndpointsWithServerCluster(GeneralDiagnostics::Id))
    {
        // If General Diagnostics cluster is implemented on this endpoint
        MatterReportingAttributeChangeCallback(endpointId, GeneralDiagnostics::Id,
                                               GeneralDiagnostics::Attributes::ActiveRadioFaults::Id);

        // Record RadioFault event
        EventNumber eventNumber;
        DataModel::List<const RadioFaultEnum> currentList(reinterpret_cast<const RadioFaultEnum *>(current.data()), current.size());
        DataModel::List<const RadioFaultEnum> previousList(reinterpret_cast<const RadioFaultEnum *>(previous.data()),
                                                           previous.size());
        Events::RadioFaultChange::Type event{ currentList, previousList };

        if (CHIP_NO_ERROR != LogEvent(event, endpointId, eventNumber))
        {
            ChipLogError(Zcl, "GeneralDiagnostics: Failed to record RadioFault event");
        }
    }
}

// Get called when the Node detects a network fault has been raised.
void GeneralDiagnosticsServer::OnNetworkFaultsDetect(const GeneralFaults<kMaxNetworkFaults> & previous,
                                                     const GeneralFaults<kMaxNetworkFaults> & current)
{
    ChipLogDetail(Zcl, "GeneralDiagnostics: OnNetworkFaultsDetect");

    for (auto endpointId : EnabledEndpointsWithServerCluster(GeneralDiagnostics::Id))
    {
        // If General Diagnostics cluster is implemented on this endpoint
        MatterReportingAttributeChangeCallback(endpointId, GeneralDiagnostics::Id,
                                               GeneralDiagnostics::Attributes::ActiveNetworkFaults::Id);

        // Record NetworkFault event
        EventNumber eventNumber;
        DataModel::List<const NetworkFaultEnum> currentList(reinterpret_cast<const NetworkFaultEnum *>(current.data()),
                                                            current.size());
        DataModel::List<const NetworkFaultEnum> previousList(reinterpret_cast<const NetworkFaultEnum *>(previous.data()),
                                                             previous.size());
        Events::NetworkFaultChange::Type event{ currentList, previousList };

        if (CHIP_NO_ERROR != LogEvent(event, endpointId, eventNumber))
        {
            ChipLogError(Zcl, "GeneralDiagnostics: Failed to record NetworkFault event");
        }
    }
}

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

namespace {

TestEventTriggerDelegate * GetTriggerDelegateOnMatchingKey(ByteSpan enableKey)
{
    if (enableKey.size() != TestEventTriggerDelegate::kEnableKeyLength)
    {
        return nullptr;
    }

    if (IsByteSpanAllZeros(enableKey))
    {
        return nullptr;
    }

    auto * triggerDelegate = chip::Server::GetInstance().GetTestEventTriggerDelegate();

    if (triggerDelegate == nullptr || !triggerDelegate->DoesEnableKeyMatch(enableKey))
    {
        return nullptr;
    }

    return triggerDelegate;
}

} // namespace

bool emberAfGeneralDiagnosticsClusterTestEventTriggerCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath,
                                                              const Commands::TestEventTrigger::DecodableType & commandData)
{
    auto * triggerDelegate = GetTriggerDelegateOnMatchingKey(commandData.enableKey);
    if (triggerDelegate == nullptr)
    {
        commandObj->AddStatus(commandPath, Status::ConstraintError);
        return true;
    }

    CHIP_ERROR handleEventTriggerResult = triggerDelegate->HandleEventTriggers(commandData.eventTrigger);

    // When HandleEventTrigger fails, we simply convert any error to INVALID_COMMAND
    commandObj->AddStatus(commandPath, (handleEventTriggerResult != CHIP_NO_ERROR) ? Status::InvalidCommand : Status::Success);
    return true;
}

bool emberAfGeneralDiagnosticsClusterTimeSnapshotCallback(CommandHandler * commandObj, ConcreteCommandPath const & commandPath,
                                                          Commands::TimeSnapshot::DecodableType const & commandData)
{
    ChipLogError(Zcl, "Received TimeSnapshot command!");

    Commands::TimeSnapshotResponse::Type response;

    System::Clock::Microseconds64 posix_time_us{ 0 };

    // Only consider real time if time sync cluster is actually enabled. Avoids
    // likelihood of frequently reporting unsynced time.
#ifdef ZCL_USING_TIME_SYNCHRONIZATION_CLUSTER_SERVER
    CHIP_ERROR posix_time_err = System::SystemClock().GetClock_RealTime(posix_time_us);
    if (posix_time_err != CHIP_NO_ERROR)
    {
        ChipLogError(Zcl, "Failed to get POSIX real time: %" CHIP_ERROR_FORMAT, posix_time_err.Format());
        posix_time_us = System::Clock::Microseconds64{ 0 };
    }
#endif // ZCL_USING_TIME_SYNCHRONIZATION_CLUSTER_SERVER

    System::Clock::Milliseconds64 system_time_ms =
        std::chrono::duration_cast<System::Clock::Milliseconds64>(Server::GetInstance().TimeSinceInit());

    response.systemTimeMs = static_cast<uint64_t>(system_time_ms.count());
    if (posix_time_us.count() != 0)
    {
        response.posixTimeMs.SetNonNull(
            static_cast<uint64_t>(std::chrono::duration_cast<System::Clock::Milliseconds64>(posix_time_us).count()));
    }
    commandObj->AddResponse(commandPath, response);
    return true;
}

bool emberAfGeneralDiagnosticsClusterPayloadTestRequestCallback(CommandHandler * commandObj,
                                                                const ConcreteCommandPath & commandPath,
                                                                const Commands::PayloadTestRequest::DecodableType & commandData)
{
    // Max allowed is 2048.
    if (commandData.count > 2048)
    {
        commandObj->AddStatus(commandPath, Status::ConstraintError);
        return true;
    }

    // Ensure Test Event triggers are enabled and key matches.
    auto * triggerDelegate = GetTriggerDelegateOnMatchingKey(commandData.enableKey);
    if (triggerDelegate == nullptr)
    {
        commandObj->AddStatus(commandPath, Status::ConstraintError);
        return true;
    }

    Commands::PayloadTestResponse::Type response;
    Platform::ScopedMemoryBufferWithSize<uint8_t> payload;
    if (!payload.Calloc(commandData.count))
    {
        commandObj->AddStatus(commandPath, Status::ResourceExhausted);
        return true;
    }

    memset(payload.Get(), commandData.value, payload.AllocatedSize());
    response.payload = ByteSpan{ payload.Get(), payload.AllocatedSize() };

    if (commandObj->AddResponseData(commandPath, response) != CHIP_NO_ERROR)
    {
        commandObj->AddStatus(commandPath, Status::ResourceExhausted);
    }

    return true;
}

void MatterGeneralDiagnosticsPluginServerInitCallback()
{
    BootReasonEnum bootReason;

    registerAttributeAccessOverride(&gAttrAccess);
    ConnectivityMgr().SetDelegate(&gDiagnosticDelegate);

    if (GetDiagnosticDataProvider().GetBootReason(bootReason) == CHIP_NO_ERROR)
    {
        GeneralDiagnosticsServer::Instance().OnDeviceReboot(bootReason);
    }
}
