/*
 *
 *    Copyright (c) 2021 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 "app-common/zap-generated/ids/Attributes.h"
#include "app-common/zap-generated/ids/Clusters.h"
#include "lib/core/CHIPTLVTags.h"
#include "protocols/interaction_model/Constants.h"
#include "system/SystemPacketBuffer.h"
#include "system/TLVPacketBufferBackingStore.h"
#include <app-common/zap-generated/cluster-objects.h>
#include <app/ClusterStateCache.h>
#include <app/data-model/DecodableList.h>
#include <app/data-model/Decode.h>
#include <app/tests/AppTestContext.h>
#include <lib/support/UnitTestContext.h>
#include <lib/support/UnitTestRegistration.h>
#include <nlunit-test.h>
#include <string.h>
#include <vector>

using TestContext = chip::Test::AppContext;
using namespace chip::app;
using namespace chip;

namespace {

nlTestSuite * gSuite = nullptr;

struct AttributeInstruction
{
    enum AttributeType
    {
        kAttributeA = 0, // int
        kAttributeB = 1, // byte string
        kAttributeC = 2, // struct
        kAttributeD = 3, // list
    };

    enum ValueType
    {
        kData   = 0,
        kStatus = 1
    };

    AttributeType mAttributeType;
    EndpointId mEndpointId;
    ValueType mValueType;
    uint8_t mInstructionId;

    AttributeInstruction() { mInstructionId = sInstructionId++; }

    bool operator<(const AttributeInstruction & instruction) const
    {
        return (mAttributeType < instruction.mAttributeType ||
                (!(mAttributeType < instruction.mAttributeType) && (mEndpointId < instruction.mEndpointId)));
    }

    AttributeInstruction(AttributeType attributeType, EndpointId endpointId, ValueType valueType) : AttributeInstruction()
    {
        mAttributeType = attributeType;
        mEndpointId    = endpointId;
        mValueType     = valueType;
    }

    AttributeId GetAttributeId() const
    {
        switch (mAttributeType)
        {
        case kAttributeA:
            return Clusters::UnitTesting::Attributes::Int16u::Id;
            break;

        case kAttributeB:
            return Clusters::UnitTesting::Attributes::OctetString::Id;
            break;

        case kAttributeC:
            return Clusters::UnitTesting::Attributes::StructAttr::Id;
            break;

        default:
            return Clusters::UnitTesting::Attributes::ListStructOctetString::Id;
            break;
        }
    }

    static uint8_t sInstructionId;
};

uint8_t AttributeInstruction::sInstructionId = 0;

using AttributeInstructionListType = std::vector<AttributeInstruction>;

class ForwardedDataCallbackValidator final
{
public:
    void SetExpectation(TLV::TLVReader & aData, EndpointId endpointId, AttributeInstruction::AttributeType attributeType)
    {
        auto length = aData.GetRemainingLength();
        std::vector<uint8_t> buffer(aData.GetReadPoint(), aData.GetReadPoint() + length);
        if (!mExpectedBuffers.empty() && endpointId == mLastEndpointId && attributeType == mLastAttributeType)
        {
            // For overriding test, the last buffered data is removed.
            mExpectedBuffers.pop_back();
        }
        mExpectedBuffers.push_back(buffer);
        mLastEndpointId    = endpointId;
        mLastAttributeType = attributeType;
    }

    void SetExpectation() { mExpectedBuffers.clear(); }

    void ValidateData(TLV::TLVReader & aData, bool isListOperation)
    {
        NL_TEST_ASSERT(gSuite, !mExpectedBuffers.empty());
        if (!mExpectedBuffers.empty() > 0)
        {
            auto buffer = mExpectedBuffers.front();
            mExpectedBuffers.erase(mExpectedBuffers.begin());
            uint32_t length = static_cast<uint32_t>(buffer.size());
            if (isListOperation)
            {
                // List operation will attach end of container
                NL_TEST_ASSERT(gSuite, length < aData.GetRemainingLength());
            }
            else
            {
                NL_TEST_ASSERT(gSuite, length == aData.GetRemainingLength());
            }
            if (length <= aData.GetRemainingLength() && length > 0)
            {
                NL_TEST_ASSERT(gSuite, memcmp(aData.GetReadPoint(), buffer.data(), length) == 0);
                if (memcmp(aData.GetReadPoint(), buffer.data(), length) != 0)
                {
                    ChipLogProgress(DataManagement, "Failed");
                }
            }
        }
    }

    void ValidateNoData() { NL_TEST_ASSERT(gSuite, mExpectedBuffers.empty()); }

private:
    std::vector<std::vector<uint8_t>> mExpectedBuffers;
    EndpointId mLastEndpointId;
    AttributeInstruction::AttributeType mLastAttributeType;
};

class DataSeriesGenerator
{
public:
    DataSeriesGenerator(ReadClient::Callback * readCallback, AttributeInstructionListType & instructionList) :
        mReadCallback(readCallback), mInstructionList(instructionList)
    {}

    void Generate(ForwardedDataCallbackValidator & dataCallbackValidator);

private:
    ReadClient::Callback * mReadCallback;
    AttributeInstructionListType & mInstructionList;
};

void DataSeriesGenerator::Generate(ForwardedDataCallbackValidator & dataCallbackValidator)
{
    ReadClient::Callback * callback = mReadCallback;
    StatusIB status;
    callback->OnReportBegin();

    for (auto & instruction : mInstructionList)
    {
        ConcreteDataAttributePath path(instruction.mEndpointId, Clusters::UnitTesting::Id, 0);
        Platform::ScopedMemoryBufferWithSize<uint8_t> handle;
        handle.Calloc(3000);
        TLV::ScopedBufferTLVWriter writer(std::move(handle), 3000);

        status            = StatusIB();
        path.mAttributeId = instruction.GetAttributeId();
        path.mDataVersion.SetValue(1);

        ChipLogProgress(DataManagement, "\t -- Generating Instruction ID %d", instruction.mInstructionId);

        if (instruction.mValueType == AttributeInstruction::kData)
        {
            switch (instruction.mAttributeType)
            {
            case AttributeInstruction::kAttributeA: {
                ChipLogProgress(DataManagement, "\t -- Generating A");

                Clusters::UnitTesting::Attributes::Int16u::TypeInfo::Type value = instruction.mInstructionId;
                NL_TEST_ASSERT(gSuite, DataModel::Encode(writer, TLV::AnonymousTag(), value) == CHIP_NO_ERROR);
                break;
            }

            case AttributeInstruction::kAttributeB: {
                ChipLogProgress(DataManagement, "\t -- Generating B");

                Clusters::UnitTesting::Attributes::OctetString::TypeInfo::Type value;
                uint8_t buf[] = { 'h', 'e', 'l', 'l', 'o' };
                value         = buf;

                NL_TEST_ASSERT(gSuite, DataModel::Encode(writer, TLV::AnonymousTag(), value) == CHIP_NO_ERROR);
                break;
            }

            case AttributeInstruction::kAttributeC: {
                ChipLogProgress(DataManagement, "\t -- Generating C");

                Clusters::UnitTesting::Attributes::StructAttr::TypeInfo::Type value;
                value.a = instruction.mInstructionId;
                value.b = true;
                NL_TEST_ASSERT(gSuite, DataModel::Encode(writer, TLV::AnonymousTag(), value) == CHIP_NO_ERROR);
                break;
            }

            case AttributeInstruction::kAttributeD: {
                ChipLogProgress(DataManagement, "\t -- Generating D");

                // buf[200] is 1.6k
                Clusters::UnitTesting::Structs::TestListStructOctet::Type buf[200];

                for (auto & i : buf)
                {
                    i.member1 = instruction.mInstructionId;
                }

                Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo::Type value;
                path.mListOp = ConcreteDataAttributePath::ListOperation::ReplaceAll;

                value = buf;
                NL_TEST_ASSERT(gSuite, DataModel::Encode(writer, TLV::AnonymousTag(), value) == CHIP_NO_ERROR);
                break;
            }

            default:
                break;
            }

            uint32_t writtenLength = writer.GetLengthWritten();
            writer.Finalize(handle);
            TLV::ScopedBufferTLVReader reader;
            reader.Init(std::move(handle), writtenLength);
            NL_TEST_ASSERT(gSuite, reader.Next() == CHIP_NO_ERROR);
            dataCallbackValidator.SetExpectation(reader, instruction.mEndpointId, instruction.mAttributeType);
            callback->OnAttributeData(path, &reader, status);
        }
        else
        {
            ChipLogProgress(DataManagement, "\t -- Generating Status");
            status.mStatus = Protocols::InteractionModel::Status::Failure;
            dataCallbackValidator.SetExpectation();
            callback->OnAttributeData(path, nullptr, status);
        }
    }

    callback->OnReportEnd();
}

class CacheValidator : public ClusterStateCache::Callback
{
public:
    CacheValidator(AttributeInstructionListType & instructionList, ForwardedDataCallbackValidator & dataCallbackValidator);

    Clusters::UnitTesting::Attributes::TypeInfo::DecodableType clusterValue;

private:
    void OnDone(ReadClient *) override {}
    void OnAttributeData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus) override
    {
        ChipLogProgress(DataManagement, "\t\t -- Validating OnAttributeData callback");
        // Ensure that the provided path is one that we're expecting to find
        auto iter = mExpectedAttributes.find(aPath);
        NL_TEST_ASSERT(gSuite, iter != mExpectedAttributes.end());

        if (aStatus.IsSuccess())
        {
            // Verify that the apData is passed as nonnull
            NL_TEST_ASSERT(gSuite, apData != nullptr);
            if (apData)
            {
                mDataCallbackValidator.ValidateData(*apData, aPath.IsListOperation());
            }
        }
        else
        {
            mDataCallbackValidator.ValidateNoData();
        }
    }

    void DecodeAttribute(const AttributeInstruction & instruction, const ConcreteAttributePath & path, ClusterStateCache * cache)
    {
        CHIP_ERROR err;
        bool gotStatus = false;

        ChipLogProgress(DataManagement, "\t\t -- Validating Instruction ID: %d", instruction.mInstructionId);

        switch (instruction.mAttributeType)
        {
        case AttributeInstruction::kAttributeA: {
            ChipLogProgress(DataManagement, "\t\t -- Validating A");

            Clusters::UnitTesting::Attributes::Int16u::TypeInfo::DecodableType v = 0;
            err = cache->Get<Clusters::UnitTesting::Attributes::Int16u::TypeInfo>(path, v);
            if (err == CHIP_ERROR_IM_STATUS_CODE_RECEIVED)
            {
                gotStatus = true;
                err       = CHIP_NO_ERROR;
            }
            else
            {
                NL_TEST_ASSERT(gSuite, err == CHIP_NO_ERROR);
                NL_TEST_ASSERT(gSuite, v == instruction.mInstructionId);
            }

            break;
        }

        case AttributeInstruction::kAttributeB: {
            ChipLogProgress(DataManagement, "\t\t -- Validating B");

            Clusters::UnitTesting::Attributes::OctetString::TypeInfo::DecodableType v;
            err = cache->Get<Clusters::UnitTesting::Attributes::OctetString::TypeInfo>(path, v);
            if (err == CHIP_ERROR_IM_STATUS_CODE_RECEIVED)
            {
                gotStatus = true;
                err       = CHIP_NO_ERROR;
            }
            else
            {
                NL_TEST_ASSERT(gSuite, err == CHIP_NO_ERROR);
                NL_TEST_ASSERT(gSuite, strncmp((char *) v.data(), "hello", v.size()) == 0);
            }

            break;
        }

        case AttributeInstruction::kAttributeC: {
            ChipLogProgress(DataManagement, "\t\t -- Validating C");

            Clusters::UnitTesting::Attributes::StructAttr::TypeInfo::DecodableType v;
            err = cache->Get<Clusters::UnitTesting::Attributes::StructAttr::TypeInfo>(path, v);
            if (err == CHIP_ERROR_IM_STATUS_CODE_RECEIVED)
            {
                gotStatus = true;
                err       = CHIP_NO_ERROR;
            }
            else
            {
                NL_TEST_ASSERT(gSuite, v.a == instruction.mInstructionId);
                NL_TEST_ASSERT(gSuite, v.b == true);
            }

            break;
        }

        case AttributeInstruction::kAttributeD: {
            ChipLogProgress(DataManagement, "\t\t -- Validating D");

            Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo::DecodableType v;
            err = cache->Get<Clusters::UnitTesting::Attributes::ListStructOctetString::TypeInfo>(path, v);
            if (err == CHIP_ERROR_IM_STATUS_CODE_RECEIVED)
            {
                gotStatus = true;
                err       = CHIP_NO_ERROR;
            }
            else
            {
                auto listIter = v.begin();
                while (listIter.Next())
                {
                    NL_TEST_ASSERT(gSuite, listIter.GetValue().member1 == instruction.mInstructionId);
                }

                NL_TEST_ASSERT(gSuite, listIter.GetStatus() == CHIP_NO_ERROR);
            }

            break;
        }
        }

        NL_TEST_ASSERT(gSuite, err == CHIP_NO_ERROR);

        if (gotStatus)
        {
            ChipLogProgress(DataManagement, "\t\t -- Validating status");
            NL_TEST_ASSERT(gSuite, instruction.mValueType == AttributeInstruction::kStatus);
        }
    }

    void DecodeClusterObject(const AttributeInstruction & instruction, const ConcreteAttributePath & path,
                             ClusterStateCache * cache)
    {
        std::list<ClusterStateCache::AttributeStatus> statusList;
        NL_TEST_ASSERT(gSuite, cache->Get(path.mEndpointId, path.mClusterId, clusterValue, statusList) == CHIP_NO_ERROR);

        if (instruction.mValueType == AttributeInstruction::kData)
        {
            NL_TEST_ASSERT(gSuite, statusList.size() == 0);

            switch (instruction.mAttributeType)
            {
            case AttributeInstruction::kAttributeA:
                ChipLogProgress(DataManagement, "\t\t -- Validating A (Cluster Obj)");
                NL_TEST_ASSERT(gSuite, clusterValue.int16u == instruction.mInstructionId);
                break;

            case AttributeInstruction::kAttributeB:
                ChipLogProgress(DataManagement, "\t\t -- Validating B (Cluster Obj)");
                NL_TEST_ASSERT(gSuite,
                               strncmp((char *) clusterValue.octetString.data(), "hello", clusterValue.octetString.size()) == 0);
                break;

            case AttributeInstruction::kAttributeC:
                ChipLogProgress(DataManagement, "\t\t -- Validating C (Cluster Obj)");
                NL_TEST_ASSERT(gSuite, clusterValue.structAttr.a == instruction.mInstructionId);
                NL_TEST_ASSERT(gSuite, clusterValue.structAttr.b == true);
                break;

            case AttributeInstruction::kAttributeD:
                ChipLogProgress(DataManagement, "\t\t -- Validating D (Cluster Obj)");

                auto listIter = clusterValue.listStructOctetString.begin();
                while (listIter.Next())
                {
                    NL_TEST_ASSERT(gSuite, listIter.GetValue().member1 == instruction.mInstructionId);
                }

                NL_TEST_ASSERT(gSuite, listIter.GetStatus() == CHIP_NO_ERROR);
                break;
            }
        }
        else
        {
            NL_TEST_ASSERT(gSuite, statusList.size() == 1);

            auto status = statusList.front();
            NL_TEST_ASSERT(gSuite, status.mPath.mEndpointId == instruction.mEndpointId);
            NL_TEST_ASSERT(gSuite, status.mPath.mClusterId == Clusters::UnitTesting::Id);
            NL_TEST_ASSERT(gSuite, status.mPath.mAttributeId == instruction.GetAttributeId());
            NL_TEST_ASSERT(gSuite, status.mStatus.mStatus == Protocols::InteractionModel::Status::Failure);
        }
    }

    void OnAttributeChanged(ClusterStateCache * cache, const ConcreteAttributePath & path) override
    {
        StatusIB status;

        // Ensure that the provided path is one that we're expecting to find
        auto iter = mExpectedAttributes.find(path);
        NL_TEST_ASSERT(gSuite, iter != mExpectedAttributes.end());

        // Once retrieved, let's erase it from the expected set so that we can catch duplicates coming back
        // as well as validating that we've seen all attributes at the end.
        mExpectedAttributes.erase(iter);

        for (auto & instruction : mInstructionSet)
        {
            if (instruction.mEndpointId == path.mEndpointId && instruction.GetAttributeId() == path.mAttributeId &&
                path.mClusterId == Clusters::UnitTesting::Id)
            {

                //
                // Validate both decoding into attribute objects as well as
                // cluster objects.
                //
                DecodeAttribute(instruction, path, cache);
                DecodeClusterObject(instruction, path, cache);
            }
        }
    }

    void OnClusterChanged(ClusterStateCache * cache, EndpointId endpointId, ClusterId clusterId) override
    {
        auto iter = mExpectedClusters.find(std::make_tuple(endpointId, clusterId));
        NL_TEST_ASSERT(gSuite, iter != mExpectedClusters.end());
        mExpectedClusters.erase(iter);
    }

    void OnEndpointAdded(ClusterStateCache * cache, EndpointId endpointId) override
    {
        auto iter = mExpectedEndpoints.find(endpointId);
        NL_TEST_ASSERT(gSuite, iter != mExpectedEndpoints.end());
        mExpectedEndpoints.erase(iter);
    }

    void OnReportEnd() override
    {
        NL_TEST_ASSERT(gSuite, mExpectedAttributes.size() == 0);
        NL_TEST_ASSERT(gSuite, mExpectedClusters.size() == 0);
        NL_TEST_ASSERT(gSuite, mExpectedEndpoints.size() == 0);
    }

    //
    // We use sets for tracking most of the expected data since we're expecting
    // unique data items being provided in the callbacks.
    //
    std::set<AttributeInstruction> mInstructionSet;
    std::set<ConcreteAttributePath> mExpectedAttributes;
    std::set<std::tuple<EndpointId, ClusterId>> mExpectedClusters;
    std::set<EndpointId> mExpectedEndpoints;

    ForwardedDataCallbackValidator & mDataCallbackValidator;
};

CacheValidator::CacheValidator(AttributeInstructionListType & instructionList,
                               ForwardedDataCallbackValidator & dataCallbackValidator) :
    mDataCallbackValidator(dataCallbackValidator)
{
    for (auto & instruction : instructionList)
    {
        //
        // We need to replace a matching instruction with the latest one we see in the list to ensure we get
        // the instruction with the highest InstructionID. Hence the erase and insert (i.e replace) operation.
        //
        mInstructionSet.erase(instruction);
        mInstructionSet.insert(instruction);
        mExpectedAttributes.insert(
            ConcreteAttributePath(instruction.mEndpointId, Clusters::UnitTesting::Id, instruction.GetAttributeId()));
        mExpectedClusters.insert(std::make_tuple(instruction.mEndpointId, Clusters::UnitTesting::Id));
        mExpectedEndpoints.insert(instruction.mEndpointId);
    }
}

void RunAndValidateSequence(AttributeInstructionListType list)
{
    ForwardedDataCallbackValidator dataCallbackValidator;
    CacheValidator client(list, dataCallbackValidator);
    ClusterStateCache cache(client);
    DataSeriesGenerator generator(&cache.GetBufferedCallback(), list);
    generator.Generate(dataCallbackValidator);
}

/*
 * This validates the cache by issuing different sequences of attribute combinations
 * and ensuring that the latest view in the cache matches up with expectations.
 *
 * The print statements indicate the expected output.
 *
 * The legend is as follows:
 *
 * E1:A1 --- Endpoint 1, Attribute A, Version 1
 *
 */
void TestCache(nlTestSuite * apSuite, void * apContext)
{
    ChipLogProgress(DataManagement, "Validating various sequences of attribute data IBs...");

    //
    // Validate a range of types and ensure that they can be successfully decoded.
    //
    ChipLogProgress(DataManagement, "E1:A1 --> E1:A1");
    RunAndValidateSequence({ AttributeInstruction(

        AttributeInstruction::kAttributeA, 1, AttributeInstruction::kData) });

    ChipLogProgress(DataManagement, "E1:B1 --> E1:B1");
    RunAndValidateSequence({ AttributeInstruction(

        AttributeInstruction::kAttributeB, 1, AttributeInstruction::kData) });

    ChipLogProgress(DataManagement, "E1:C1 --> E1:C1");
    RunAndValidateSequence({ AttributeInstruction(AttributeInstruction::kAttributeC, 1, AttributeInstruction::kData) });

    ChipLogProgress(DataManagement, "E1:D1 --> E1:D1");
    RunAndValidateSequence({ AttributeInstruction(AttributeInstruction::kAttributeD, 1, AttributeInstruction::kData) });

    //
    // Validate that a newer version of a data item over-rides the
    // previous copy.
    //
    ChipLogProgress(DataManagement, "E1:D1 E1:D2 --> E1:D2");
    RunAndValidateSequence({ AttributeInstruction(AttributeInstruction::kAttributeD, 1, AttributeInstruction::kData),
                             AttributeInstruction(AttributeInstruction::kAttributeD, 1, AttributeInstruction::kData) });

    //
    // Validate that a newer StatusIB over-rides a previous data value.
    //
    ChipLogProgress(DataManagement, "E1:D1 E1:D2s --> E1:D2s");
    RunAndValidateSequence({ AttributeInstruction(AttributeInstruction::kAttributeD, 1, AttributeInstruction::kData),
                             AttributeInstruction(AttributeInstruction::kAttributeD, 1, AttributeInstruction::kStatus) });

    //
    // Validate that a newer data value over-rides a previous status value.
    //
    ChipLogProgress(DataManagement, "E1:D1s E1:D2 --> E1:D2");
    RunAndValidateSequence({ AttributeInstruction(AttributeInstruction::kAttributeD, 1, AttributeInstruction::kStatus),
                             AttributeInstruction(AttributeInstruction::kAttributeD, 1, AttributeInstruction::kData) });

    //
    // Validate data across different endpoints.
    //
    ChipLogProgress(DataManagement, "E0:D1 E1:D2 --> E0:D1 E1:D2");
    RunAndValidateSequence({ AttributeInstruction(AttributeInstruction::kAttributeD, 0, AttributeInstruction::kData),
                             AttributeInstruction(AttributeInstruction::kAttributeD, 1, AttributeInstruction::kData) });

    ChipLogProgress(DataManagement, "E0:A1 E0:B2 E0:A3 E0:B4 --> E0:A3 E0:B4");
    RunAndValidateSequence({ AttributeInstruction(AttributeInstruction::kAttributeA, 0, AttributeInstruction::kData),
                             AttributeInstruction(AttributeInstruction::kAttributeB, 0, AttributeInstruction::kData),
                             AttributeInstruction(AttributeInstruction::kAttributeA, 0, AttributeInstruction::kData),
                             AttributeInstruction(AttributeInstruction::kAttributeB, 0, AttributeInstruction::kData) });
}

// clang-format off
const nlTest sTests[] =
{
    NL_TEST_DEF("TestCache", TestCache),
    NL_TEST_SENTINEL()
};

nlTestSuite theSuite =
{
    "TestClusterStateCache",
    &sTests[0],
    TestContext::Initialize,
    TestContext::Finalize
};

}
// clang-format on

int TestClusterStateCache()
{
    gSuite = &theSuite;
    return chip::ExecuteTestsWithContext<TestContext>(&theSuite);
}

CHIP_REGISTER_TEST_SUITE(TestClusterStateCache)
