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

/**
 *    @file
 *      This file implements a test for  CHIP Interaction Model Event logging
 *
 */

#include <app/EventLoggingDelegate.h>
#include <app/EventLoggingTypes.h>
#include <app/EventManagement.h>
#include <app/InteractionModelEngine.h>
#include <app/tests/AppTestContext.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/TLV.h>
#include <lib/core/TLVDebug.h>
#include <lib/core/TLVUtilities.h>
#include <lib/support/CHIPCounter.h>
#include <lib/support/EnforceFormat.h>
#include <lib/support/ErrorStr.h>
#include <lib/support/UnitTestContext.h>
#include <lib/support/UnitTestRegistration.h>
#include <lib/support/logging/Constants.h>
#include <messaging/ExchangeContext.h>
#include <messaging/Flags.h>
#include <platform/CHIPDeviceLayer.h>
#include <system/TLVPacketBufferBackingStore.h>

#include <nlunit-test.h>

namespace {

static uint8_t gDebugEventBuffer[2048];
static uint8_t gInfoEventBuffer[2048];
static uint8_t gCritEventBuffer[2048];
static chip::app::CircularEventBuffer gCircularEventBuffer[3];

class TestContext : public chip::Test::AppContext
{
public:
    static int Initialize(void * context)
    {
        if (AppContext::Initialize(context) != SUCCESS)
            return FAILURE;

        auto * ctx = static_cast<TestContext *>(context);

        if (ctx->mEventCounter.Init(0) != CHIP_NO_ERROR)
        {
            return FAILURE;
        }

        chip::app::LogStorageResources logStorageResources[] = {
            { &gDebugEventBuffer[0], sizeof(gDebugEventBuffer), chip::app::PriorityLevel::Debug },
            { &gInfoEventBuffer[0], sizeof(gInfoEventBuffer), chip::app::PriorityLevel::Info },
            { &gCritEventBuffer[0], sizeof(gCritEventBuffer), chip::app::PriorityLevel::Critical },
        };

        chip::app::EventManagement::CreateEventManagement(&ctx->GetExchangeManager(),
                                                          sizeof(logStorageResources) / sizeof(logStorageResources[0]),
                                                          gCircularEventBuffer, logStorageResources, &ctx->mEventCounter);

        return SUCCESS;
    }

    static int Finalize(void * context)
    {
        chip::app::EventManagement::DestroyEventManagement();

        if (AppContext::Finalize(context) != SUCCESS)
            return FAILURE;

        return SUCCESS;
    }

private:
    chip::MonotonicallyIncreasingCounter<chip::EventNumber> mEventCounter;
};

class TestEventGenerator : public chip::app::EventLoggingDelegate
{
public:
    CHIP_ERROR WriteEvent(chip::TLV::TLVWriter & aWriter)
    {
        chip::TLV::TLVType dataContainerType;
        ReturnErrorOnFailure(aWriter.StartContainer(chip::TLV::ContextTag(chip::to_underlying(chip::app::EventDataIB::Tag::kData)),
                                                    chip::TLV::kTLVType_Structure, dataContainerType));
        ReturnErrorOnFailure(aWriter.Put(chip::TLV::ContextTag(1), static_cast<uint32_t>(1)));
        ReturnErrorOnFailure(aWriter.Put(chip::TLV::ContextTag(2), static_cast<uint32_t>(2)));
        return aWriter.EndContainer(dataContainerType);
    }
};

static void CheckLogEventOverFlow(nlTestSuite * apSuite, void * apContext)
{
    CHIP_ERROR err           = CHIP_NO_ERROR;
    chip::EventNumber oldEid = 0;
    chip::EventNumber eid    = 0;
    chip::app::EventOptions options;
    TestEventGenerator testEventGenerator;

    chip::EndpointId testEndpointId = 1;
    chip::ClusterId testClusterId   = 0x00000006;
    chip::EventId testEvent         = 1;
    options.mPath                   = { testEndpointId, testClusterId, testEvent };
    options.mPriority               = chip::app::PriorityLevel::Debug;

    chip::app::EventManagement & logMgmt = chip::app::EventManagement::GetInstance();
    int alternate                        = 0;
    for (int i = 0; i < 500; i++)
    {
        switch (alternate)
        {
        case 0:
            options.mPriority = chip::app::PriorityLevel::Critical;
            break;
        case 1:
            options.mPriority = chip::app::PriorityLevel::Debug;
            break;
        case 2:
            options.mPriority = chip::app::PriorityLevel::Critical;
            break;
        case 3:
            options.mPriority = chip::app::PriorityLevel::Debug;
            break;
        case 4:
            options.mPriority = chip::app::PriorityLevel::Critical;
            break;
        case 5:
            options.mPriority = chip::app::PriorityLevel::Debug;
            break;
        case 6:
            options.mPriority = chip::app::PriorityLevel::Critical;
            break;
        case 7:
            options.mPriority = chip::app::PriorityLevel::Debug;
            break;
        case 8:
            options.mPriority = chip::app::PriorityLevel::Critical;
            break;
        case 9:
            options.mPriority = chip::app::PriorityLevel::Debug;
            break;
        }
        alternate = i % 10;

        err = logMgmt.LogEvent(&testEventGenerator, options, eid);
        NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
        if (eid > 0)
        {
            NL_TEST_ASSERT(apSuite, eid == oldEid + 1);
            oldEid = eid;
        }
    }
}

const nlTest sTests[] = { NL_TEST_DEF("CheckLogEventOverFlow", CheckLogEventOverFlow), NL_TEST_SENTINEL() };

// clang-format off
nlTestSuite sSuite =
{
    "TestEventOverflow",
    &sTests[0],
    TestContext::Initialize,
    TestContext::Finalize
};
// clang-format on

} // namespace

int TestEventOverflow()
{
    return chip::ExecuteTestsWithContext<TestContext>(&sSuite);
}

CHIP_REGISTER_TEST_SUITE(TestEventOverflow)
