/*
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2018 Google LLC.
 *    Copyright (c) 2017 Nest Labs, Inc.
 *    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 declares mock event generator and example
 *
 */

#include "MockEvents.h"
#include "common.h"
#include <app/EventLoggingTypes.h>
#include <app/EventManagement.h>
#include <lib/support/ErrorStr.h>
#include <platform/CHIPDeviceLayer.h>
#include <protocols/secure_channel/PASESession.h>
#include <system/SystemPacketBuffer.h>
#include <transport/SessionManager.h>

static chip::TLV::Tag kLivenessDeviceStatus = chip::TLV::ContextTag(1);
static bool gMockEventStop                  = false;
static bool gEventIsStopped                 = false;

EventGenerator::EventGenerator(size_t aNumStates, size_t aInitialState) : mNumStates(aNumStates), mState(aInitialState) {}

size_t EventGenerator::GetNumStates()
{
    return mNumStates;
}

LivenessEventGenerator::LivenessEventGenerator(void) : EventGenerator(10, 0) {}

void LivenessEventGenerator::Generate(void)
{
    // Scenario: monitoring liveness for two devices -- self and remote.  Remote device goes offline and returns.
    switch (mState)
    {
    case 0:
        LogLiveness(kTestNodeId, kTestEndpointId, LIVENESS_DEVICE_STATUS_ONLINE, kTestChangeEvent1,
                    chip::app::PriorityLevel::Critical);
        break;

    case 1:
        LogLiveness(kTestNodeId, kTestEndpointId, LIVENESS_DEVICE_STATUS_ONLINE, kTestChangeEvent2,
                    chip::app::PriorityLevel::Debug);
        break;

    case 2:
        LogLiveness(kTestNodeId, kTestEndpointId, LIVENESS_DEVICE_STATUS_ONLINE, kTestChangeEvent1,
                    chip::app::PriorityLevel::Critical);
        break;

    case 3:
        LogLiveness(kTestNodeId, kTestEndpointId, LIVENESS_DEVICE_STATUS_UNREACHABLE, kTestChangeEvent2,
                    chip::app::PriorityLevel::Debug);
        break;

    case 4:
        LogLiveness(kTestNodeId, kTestEndpointId, LIVENESS_DEVICE_STATUS_ONLINE, kTestChangeEvent1,
                    chip::app::PriorityLevel::Critical);
        break;

    case 5:
        LogLiveness(kTestNodeId, kTestEndpointId, LIVENESS_DEVICE_STATUS_REBOOTING, kTestChangeEvent2,
                    chip::app::PriorityLevel::Debug);
        break;

    case 6:
        LogLiveness(kTestNodeId, kTestEndpointId, LIVENESS_DEVICE_STATUS_ONLINE, kTestChangeEvent1,
                    chip::app::PriorityLevel::Critical);
        break;

    case 7:
        LogLiveness(kTestNodeId, kTestEndpointId, LIVENESS_DEVICE_STATUS_ONLINE, kTestChangeEvent2,
                    chip::app::PriorityLevel::Debug);
        break;

    case 8:
        LogLiveness(kTestNodeId, kTestEndpointId, LIVENESS_DEVICE_STATUS_ONLINE, kTestChangeEvent1,
                    chip::app::PriorityLevel::Critical);
        break;

    case 9:
        LogLiveness(kTestNodeId, kTestEndpointId, LIVENESS_DEVICE_STATUS_ONLINE, kTestChangeEvent2,
                    chip::app::PriorityLevel::Debug);
        break;

    default:
        mState = 0;
    }

    mState = (mState + 1) % mNumStates;
}

CHIP_ERROR LivenessEventGenerator::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(kLivenessDeviceStatus, mStatus));
    return aWriter.EndContainer(dataContainerType);
}

chip::EventNumber LivenessEventGenerator::LogLiveness(chip::NodeId aNodeId, chip::EndpointId aEndpointId,
                                                      LivenessDeviceStatus aStatus, chip::EventId aEventId,
                                                      chip::app::PriorityLevel aPriorityLevel)
{
    chip::app::EventManagement & logManager = chip::app::EventManagement::GetInstance();
    chip::EventNumber number                = 0;
    chip::app::EventOptions options;
    options.mPath     = { aEndpointId, kTestClusterId, aEventId };
    options.mPriority = aPriorityLevel;
    mStatus           = static_cast<int32_t>(aStatus);
    logManager.LogEvent(this, options, number);
    return number;
}

MockEventGenerator * MockEventGenerator::GetInstance(void)
{
    static MockEventGeneratorImpl gMockEventGenerator;
    return &gMockEventGenerator;
}

MockEventGeneratorImpl::MockEventGeneratorImpl(void) :
    mpExchangeMgr(nullptr), mTimeBetweenEvents(0), mEventWraparound(false), mpEventGenerator(nullptr), mEventsLeft(0)
{}

CHIP_ERROR MockEventGeneratorImpl::Init(chip::Messaging::ExchangeManager * apExchangeMgr, EventGenerator * apEventGenerator,
                                        uint32_t aDelayBetweenEvents, bool aWraparound)
{
    CHIP_ERROR err     = CHIP_NO_ERROR;
    mpExchangeMgr      = apExchangeMgr;
    mpEventGenerator   = apEventGenerator;
    mTimeBetweenEvents = aDelayBetweenEvents;
    mEventWraparound   = aWraparound;

    if (mEventWraparound)
        mEventsLeft = INT32_MAX;
    else
        mEventsLeft = mpEventGenerator->GetNumStates();

    if (mTimeBetweenEvents != 0)
        mpExchangeMgr->GetSessionManager()->SystemLayer()->StartTimer(chip::System::Clock::Milliseconds32(mTimeBetweenEvents),
                                                                      HandleNextEvent, this);

    return err;
}

void MockEventGeneratorImpl::HandleNextEvent(chip::System::Layer * apSystemLayer, void * apAppState)
{
    MockEventGeneratorImpl * generator = static_cast<MockEventGeneratorImpl *>(apAppState);
    if (gMockEventStop)
    {
        gEventIsStopped = true;
        apSystemLayer->CancelTimer(HandleNextEvent, generator);
    }
    else
    {
        generator->mpEventGenerator->Generate();
        generator->mEventsLeft--;
        if ((generator->mEventWraparound) || (generator->mEventsLeft > 0))
        {
            apSystemLayer->StartTimer(chip::System::Clock::Milliseconds32(generator->mTimeBetweenEvents), HandleNextEvent,
                                      generator);
        }
    }
}

void MockEventGeneratorImpl::SetEventGeneratorStop()
{
    gMockEventStop = true;

    // If the timer is running, make it expire right away.
    // This helps quit the standalone app in an orderly way without
    // spurious leaked timers.
    if (mTimeBetweenEvents != 0)
        mpExchangeMgr->GetSessionManager()->SystemLayer()->StartTimer(chip::System::Clock::kZero, HandleNextEvent, this);
}

bool MockEventGeneratorImpl::IsEventGeneratorStopped()
{
    if (gEventIsStopped)
    {
        gMockEventStop  = false;
        gEventIsStopped = false;
        return true;
    }

    return false;
}
