/*
 *    Copyright (c) 2024 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 "app/data-model-provider/ActionReturnStatus.h"
#include <app/tests/test-interaction-model-api.h>

#include <app/InteractionModelEngine.h>
#include <app/MessageDef/AttributeReportIBs.h>
#include <app/codegen-data-model-provider/Instance.h>
#include <app/util/basic-types.h>
#include <app/util/mock/Constants.h>
#include <app/util/mock/Functions.h>
#include <lib/core/CHIPCore.h>
#include <messaging/ReliableMessageContext.h>

using namespace chip::app::DataModel;

namespace chip {
uint8_t Test::attributeDataTLV[CHIP_CONFIG_DEFAULT_UDP_MTU_SIZE];
size_t Test::attributeDataTLVLen = 0;

namespace app {

class TestOnlyAttributeValueEncoderAccessor
{
public:
    TestOnlyAttributeValueEncoderAccessor(AttributeValueEncoder & encoder) : mEncoder(encoder) {}

    AttributeReportIBs::Builder & Builder() { return mEncoder.mAttributeReportIBsBuilder; }

    void SetState(const AttributeEncodeState & state) { mEncoder.mEncodeState = state; }

private:
    AttributeValueEncoder & mEncoder;
};

// Used by the code in TestWriteInteraction.cpp (and generally tests that interact with the WriteHandler may need this).
const EmberAfAttributeMetadata * GetAttributeMetadata(const ConcreteAttributePath & aConcreteClusterPath)
{
    // Note: This test does not make use of the real attribute metadata.
    static EmberAfAttributeMetadata stub = { .defaultValue = EmberAfDefaultOrMinMaxAttributeValue(uint32_t(0)) };
    return &stub;
}

// Used by the code in TestWriteInteraction.cpp (and generally tests that interact with the WriteHandler may need this).
CHIP_ERROR WriteSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor, const ConcreteDataAttributePath & aPath,
                                  TLV::TLVReader & aReader, WriteHandler * aWriteHandler)
{
    if (aPath.mDataVersion.HasValue() && aPath.mDataVersion.Value() == Test::kRejectedDataVersion)
    {
        return aWriteHandler->AddStatus(aPath, Protocols::InteractionModel::Status::DataVersionMismatch);
    }

    TLV::TLVWriter writer;
    writer.Init(chip::Test::attributeDataTLV);
    writer.CopyElement(TLV::AnonymousTag(), aReader);
    chip::Test::attributeDataTLVLen = writer.GetLengthWritten();
    return aWriteHandler->AddStatus(aPath, Protocols::InteractionModel::Status::Success);
}

// Used by the code in TestAclAttribute.cpp (and generally tests that interact with the InteractionModelEngine may need this).
bool ConcreteAttributePathExists(const ConcreteAttributePath & aPath)
{
    return aPath.mClusterId != Test::kTestDeniedClusterId1;
}

// Used by the code in TestAclAttribute.cpp (and generally tests that interact with the InteractionModelEngine may need this).
Protocols::InteractionModel::Status CheckEventSupportStatus(const ConcreteEventPath & aPath)
{
    if (aPath.mClusterId == Test::kTestDeniedClusterId1)
    {
        return Protocols::InteractionModel::Status::UnsupportedCluster;
    }

    return Protocols::InteractionModel::Status::Success;
}

// strong defintion in TestCommandInteraction.cpp
__attribute__((weak)) Protocols::InteractionModel::Status
ServerClusterCommandExists(const ConcreteCommandPath & aRequestCommandPath)
{
    // Mock cluster catalog, only support commands on one cluster on one endpoint.
    using Protocols::InteractionModel::Status;

    return Status::Success;
}

// strong defintion in TestCommandInteraction.cpp
__attribute__((weak)) void DispatchSingleClusterCommand(const ConcreteCommandPath & aRequestCommandPath,
                                                        chip::TLV::TLVReader & aReader, CommandHandler * apCommandObj)
{}

// Used by the code in TestReadInteraction.cpp (and generally tests that interact with the Reporting Engine may need this).
bool IsClusterDataVersionEqual(const ConcreteClusterPath & aConcreteClusterPath, DataVersion aRequiredVersion)
{
    return (Test::kTestDataVersion1 == aRequiredVersion);
}

// Used by the code in TestReadInteraction.cpp.
bool IsDeviceTypeOnEndpoint(DeviceTypeId deviceType, EndpointId endpoint)
{
    return false;
}

// Used by the code in TestReadInteraction.cpp (and generally tests that interact with the Reporting Engine may need this).
CHIP_ERROR ReadSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor, bool aIsFabricFiltered,
                                 const ConcreteReadAttributePath & aPath, AttributeReportIBs::Builder & aAttributeReports,
                                 AttributeEncodeState * apEncoderState)
{
    if (aPath.mClusterId >= Test::kMockEndpointMin)
    {
        return Test::ReadSingleMockClusterData(aSubjectDescriptor.fabricIndex, aPath, aAttributeReports, apEncoderState);
    }

    if (!(aPath.mClusterId == Test::kTestClusterId && aPath.mEndpointId == Test::kTestEndpointId))
    {
        AttributeReportIB::Builder & attributeReport = aAttributeReports.CreateAttributeReport();
        ReturnErrorOnFailure(aAttributeReports.GetError());
        ChipLogDetail(DataManagement, "TEST Cluster %" PRIx32 ", Field %" PRIx32 " is dirty", aPath.mClusterId, aPath.mAttributeId);

        AttributeStatusIB::Builder & attributeStatus = attributeReport.CreateAttributeStatus();
        ReturnErrorOnFailure(attributeReport.GetError());
        AttributePathIB::Builder & attributePath = attributeStatus.CreatePath();
        ReturnErrorOnFailure(attributeStatus.GetError());

        attributePath.Endpoint(aPath.mEndpointId).Cluster(aPath.mClusterId).Attribute(aPath.mAttributeId).EndOfAttributePathIB();
        ReturnErrorOnFailure(attributePath.GetError());
        StatusIB::Builder & errorStatus = attributeStatus.CreateErrorStatus();
        ReturnErrorOnFailure(attributeStatus.GetError());
        errorStatus.EncodeStatusIB(StatusIB(Protocols::InteractionModel::Status::UnsupportedAttribute));
        ReturnErrorOnFailure(errorStatus.GetError());
        ReturnErrorOnFailure(attributeStatus.EndOfAttributeStatusIB());
        return attributeReport.EndOfAttributeReportIB();
    }

    return AttributeValueEncoder(aAttributeReports, aSubjectDescriptor, aPath, 0 /* dataVersion */).Encode(Test::kTestFieldValue1);
}

TestImCustomDataModel & TestImCustomDataModel::Instance()
{
    static TestImCustomDataModel model;
    return model;
}

ActionReturnStatus TestImCustomDataModel::ReadAttribute(const ReadAttributeRequest & request, AttributeValueEncoder & encoder)
{
    AttributeEncodeState mutableState(&encoder.GetState()); // provide a state copy to start.

    CHIP_ERROR err = ReadSingleClusterData(request.subjectDescriptor.value_or(Access::SubjectDescriptor()),
                                           request.readFlags.Has(ReadFlags::kFabricFiltered), request.path,
                                           TestOnlyAttributeValueEncoderAccessor(encoder).Builder(), &mutableState);

    // state must survive CHIP_ERRORs as it is used for chunking
    TestOnlyAttributeValueEncoderAccessor(encoder).SetState(mutableState);

    return err;
}

ActionReturnStatus TestImCustomDataModel::WriteAttribute(const WriteAttributeRequest & request, AttributeValueDecoder & decoder)
{
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

ActionReturnStatus TestImCustomDataModel::Invoke(const InvokeRequest & request, chip::TLV::TLVReader & input_arguments,
                                                 CommandHandler * handler)
{
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

EndpointId TestImCustomDataModel::FirstEndpoint()
{
    return CodegenDataModelProviderInstance()->FirstEndpoint();
}

EndpointId TestImCustomDataModel::NextEndpoint(EndpointId before)
{
    return CodegenDataModelProviderInstance()->NextEndpoint(before);
}

ClusterEntry TestImCustomDataModel::FirstCluster(EndpointId endpoint)
{
    return CodegenDataModelProviderInstance()->FirstCluster(endpoint);
}

ClusterEntry TestImCustomDataModel::NextCluster(const ConcreteClusterPath & before)
{
    return CodegenDataModelProviderInstance()->NextCluster(before);
}

std::optional<ClusterInfo> TestImCustomDataModel::GetClusterInfo(const ConcreteClusterPath & path)
{
    return CodegenDataModelProviderInstance()->GetClusterInfo(path);
}

AttributeEntry TestImCustomDataModel::FirstAttribute(const ConcreteClusterPath & cluster)
{
    return CodegenDataModelProviderInstance()->FirstAttribute(cluster);
}

AttributeEntry TestImCustomDataModel::NextAttribute(const ConcreteAttributePath & before)
{
    return CodegenDataModelProviderInstance()->NextAttribute(before);
}

std::optional<AttributeInfo> TestImCustomDataModel::GetAttributeInfo(const ConcreteAttributePath & path)
{
    return CodegenDataModelProviderInstance()->GetAttributeInfo(path);
}

CommandEntry TestImCustomDataModel::FirstAcceptedCommand(const ConcreteClusterPath & cluster)
{
    return CodegenDataModelProviderInstance()->FirstAcceptedCommand(cluster);
}

CommandEntry TestImCustomDataModel::NextAcceptedCommand(const ConcreteCommandPath & before)
{
    return CodegenDataModelProviderInstance()->NextAcceptedCommand(before);
}

std::optional<CommandInfo> TestImCustomDataModel::GetAcceptedCommandInfo(const ConcreteCommandPath & path)
{
    return CodegenDataModelProviderInstance()->GetAcceptedCommandInfo(path);
}

ConcreteCommandPath TestImCustomDataModel::FirstGeneratedCommand(const ConcreteClusterPath & cluster)
{
    return CodegenDataModelProviderInstance()->FirstGeneratedCommand(cluster);
}

ConcreteCommandPath TestImCustomDataModel::NextGeneratedCommand(const ConcreteCommandPath & before)
{
    return CodegenDataModelProviderInstance()->NextGeneratedCommand(before);
}

} // namespace app
} // namespace chip
