/**
 *
 *    Copyright (c) 2020 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 "on-off-server.h"

#include <app-common/zap-generated/attributes/Accessors.h>
#include <app/data-model/Nullable.h>
#include <app/reporting/reporting.h>
#include <app/util/af-event.h>
#include <app/util/af.h>
#include <app/util/util.h>

#ifdef EMBER_AF_PLUGIN_SCENES
#include <app/clusters/scenes/scenes.h>
#endif // EMBER_AF_PLUGIN_SCENES

using namespace chip;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::OnOff;

/**********************************************************
 * Attributes Definition
 *********************************************************/

static OnOffEffect * firstEffect = nullptr;
OnOffServer OnOffServer::instance;

/**********************************************************
 * Function definition
 *********************************************************/

static OnOffEffect * inst(EndpointId endpoint);

/**********************************************************
 * OnOff Implementation
 *********************************************************/

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

bool OnOffServer::HasFeature(chip::EndpointId endpoint, OnOffFeature feature)
{
    bool success;
    uint32_t featureMap;
    success = (Attributes::FeatureMap::Get(endpoint, &featureMap) == EMBER_ZCL_STATUS_SUCCESS);

    return success ? ((featureMap & to_underlying(feature)) != 0) : false;
}

EmberAfStatus OnOffServer::getOnOffValue(chip::EndpointId endpoint, bool * currentOnOffValue)
{
    // read current on/off value
    EmberAfStatus status = Attributes::OnOff::Get(endpoint, currentOnOffValue);
    if (status != EMBER_ZCL_STATUS_SUCCESS)
    {
        emberAfOnOffClusterPrintln("ERR: reading on/off %x", status);
    }

    emberAfOnOffClusterPrintln("On/Off ep%d value: %d", endpoint, *currentOnOffValue);

    return status;
}

/** @brief On/off Cluster Set Value
 *
 * This function is called when the on/off value needs to be set, either through
 * normal channels or as a result of a level change.
 *
 * @param endpoint   Ver.: always
 * @param command   Ver.: always
 * @param initiatedByLevelChange   Ver.: always
 */
EmberAfStatus OnOffServer::setOnOffValue(chip::EndpointId endpoint, chip::CommandId command, bool initiatedByLevelChange)
{
    EmberAfStatus status;
    bool currentValue, newValue;

    emberAfOnOffClusterPrintln("On/Off set value: %x %x", endpoint, static_cast<uint8_t>(command));

    // read current on/off value
    status = Attributes::OnOff::Get(endpoint, &currentValue);
    if (status != EMBER_ZCL_STATUS_SUCCESS)
    {
        emberAfOnOffClusterPrintln("ERR: reading on/off %x", status);
        return status;
    }

    // if the value is already what we want to set it to then do nothing
    if ((!currentValue && command == Commands::Off::Id) || (currentValue && command == Commands::On::Id))
    {
        emberAfOnOffClusterPrintln("On/off already set to new value");
        return EMBER_ZCL_STATUS_SUCCESS;
    }

    // we either got a toggle, or an on when off, or an off when on,
    // so we need to swap the value
    newValue = !currentValue;
    emberAfOnOffClusterPrintln("Toggle on/off from %x to %x", currentValue, newValue);

    // the sequence of updating on/off attribute and kick off level change effect should
    // be depend on whether we are turning on or off. If we are turning on the light, we
    // should update the on/off attribute before kicking off level change, if we are
    // turning off the light, we should do the opposite, that is kick off level change
    // before updating the on/off attribute.
    if (newValue) // Set On
    {
        if (SupportsLightingApplications(endpoint))
        {
            uint16_t onTime = 0;
            Attributes::OnTime::Get(endpoint, &onTime);

            if (onTime == 0)
            {
                emberAfOnOffClusterPrintln("On Command - OffWaitTime :  0");
                Attributes::OffWaitTime::Set(endpoint, 0);

                // Stop timer on the endpoint
                EmberEventControl * event = getEventControl(endpoint);
                if (event != nullptr)
                {
                    emberEventControlSetInactive(event);
                    emberAfOnOffClusterPrintln("On/Toggle Command - Stop Timer");
                }
            }

            Attributes::GlobalSceneControl::Set(endpoint, true);
        }

        // write the new on/off value
        status = Attributes::OnOff::Set(endpoint, newValue);
        if (status != EMBER_ZCL_STATUS_SUCCESS)
        {
            emberAfOnOffClusterPrintln("ERR: writing on/off %x", status);
            return status;
        }

#ifdef EMBER_AF_PLUGIN_LEVEL_CONTROL
        // If initiatedByLevelChange is false, then we assume that the level change
        // ZCL stuff has not happened and we do it here
        if (!initiatedByLevelChange && emberAfContainsServer(endpoint, LevelControl::Id))
        {
            emberAfOnOffClusterLevelControlEffectCallback(endpoint, newValue);
        }
#endif
#ifdef EMBER_AF_PLUGIN_MODE_SELECT
        // If OnMode is not a null value, then change the current mode to it.
        if (emberAfContainsServer(endpoint, ModeSelect::Id) &&
            emberAfContainsAttribute(endpoint, ModeSelect::Id, ModeSelect::Attributes::OnMode::Id))
        {
            ModeSelect::Attributes::OnMode::TypeInfo::Type onMode;
            if (ModeSelect::Attributes::OnMode::Get(endpoint, onMode) == EMBER_ZCL_STATUS_SUCCESS && !onMode.IsNull())
            {
                emberAfOnOffClusterPrintln("Changing Current Mode to %x", onMode.Value());
                status = ModeSelect::Attributes::CurrentMode::Set(endpoint, onMode.Value());
            }
        }
#endif
    }
    else // Set Off
    {
        if (SupportsLightingApplications(endpoint))
        {
            emberAfOnOffClusterPrintln("Off Command - OnTime :  0");
            Attributes::OnTime::Set(endpoint, 0); // Reset onTime
        }

#ifdef EMBER_AF_PLUGIN_LEVEL_CONTROL
        // If initiatedByLevelChange is false, then we assume that the level change
        // ZCL stuff has not happened and we do it here
        if (!initiatedByLevelChange && emberAfContainsServer(endpoint, LevelControl::Id))
        {
            emberAfOnOffClusterLevelControlEffectCallback(endpoint, newValue);
        }
        else
        {
#endif
            // write the new on/off value
            status = Attributes::OnOff::Set(endpoint, newValue);
            if (status != EMBER_ZCL_STATUS_SUCCESS)
            {
                emberAfOnOffClusterPrintln("ERR: writing on/off %x", status);
                return status;
            }
#ifdef EMBER_AF_PLUGIN_LEVEL_CONTROL
        }
#endif
    }

#ifdef EMBER_AF_PLUGIN_SCENES
    // the scene has been changed (the value of on/off has changed) so
    // the current scene as described in the attribute table is invalid,
    // so mark it as invalid (just writes the valid/invalid attribute)
    if (emberAfContainsServer(endpoint, Scenes::Id))
    {
        emberAfScenesClusterMakeInvalidCallback(endpoint);
    }
#endif // EMBER_AF_PLUGIN_SCENES

    // The returned status is based solely on the On/Off cluster.  Errors in the
    // Level Control and/or Scenes cluster are ignored.
    return EMBER_ZCL_STATUS_SUCCESS;
}

void OnOffServer::initOnOffServer(chip::EndpointId endpoint)
{
#ifndef IGNORE_ON_OFF_CLUSTER_START_UP_ON_OFF
    // StartUp behavior relies on OnOff and StartUpOnOff attributes being non-volatile.
    if (SupportsLightingApplications(endpoint) && areStartUpOnOffServerAttributesNonVolatile(endpoint))
    {
        // Read the StartUpOnOff attribute and set the OnOff attribute as per
        // following from zcl 7 14-0127-20i-zcl-ch-3-general.doc.
        // 3.8.2.2.5	StartUpOnOff Attribute
        // The StartUpOnOff attribute SHALL define the desired startup behavior of a
        // lamp device when it is supplied with power and this state SHALL be
        // reflected in the OnOff attribute.  The values of the StartUpOnOff
        // attribute are listed below.
        // Table 3 46. Values of the StartUpOnOff Attribute
        // Value      Action on power up
        // 0x00       Set the OnOff attribute to 0 (off).
        // 0x01       Set the OnOff attribute to 1 (on).
        // 0x02       If the previous value of the OnOff attribute is equal to 0,
        //            set the OnOff attribute to 1.If the previous value of the OnOff
        //            attribute is equal to 1, set the OnOff attribute to 0 (toggle).
        // 0x03-0xfe  These values are reserved.  No action.
        // 0xff      This value cannot happen.
        // null       Set the OnOff attribute to its previous value.

        bool onOffValueForStartUp = false;
        EmberAfStatus status      = getOnOffValueForStartUp(endpoint, onOffValueForStartUp);
        if (status == EMBER_ZCL_STATUS_SUCCESS)
        {
            status = setOnOffValue(endpoint, onOffValueForStartUp, true);
        }

#ifdef EMBER_AF_PLUGIN_MODE_SELECT
        // If OnMode is not a null value, then change the current mode to it.
        if (onOffValueForStartUp && emberAfContainsServer(endpoint, ModeSelect::Id) &&
            emberAfContainsAttribute(endpoint, ModeSelect::Id, ModeSelect::Attributes::OnMode::Id))
        {
            ModeSelect::Attributes::OnMode::TypeInfo::Type onMode;
            if (ModeSelect::Attributes::OnMode::Get(endpoint, onMode) == EMBER_ZCL_STATUS_SUCCESS && !onMode.IsNull())
            {
                emberAfOnOffClusterPrintln("Changing Current Mode to %x", onMode.Value());
                status = ModeSelect::Attributes::CurrentMode::Set(endpoint, onMode.Value());
            }
        }
#endif
    }
#endif // IGNORE_ON_OFF_CLUSTER_START_UP_ON_OFF
    emberAfPluginOnOffClusterServerPostInitCallback(endpoint);
}

/** @brief Get the OnOff value when server starts.
 *
 * This function determines how StartUpOnOff affects the OnOff value when the server starts.
 *
 * @param endpoint   Ver.: always
 * @param onOffValueForStartUp Ver.: always
 */
EmberAfStatus OnOffServer::getOnOffValueForStartUp(chip::EndpointId endpoint, bool & onOffValueForStartUp)
{
    app::DataModel::Nullable<OnOff::OnOffStartUpOnOff> startUpOnOff;
    EmberAfStatus status = Attributes::StartUpOnOff::Get(endpoint, startUpOnOff);
    if (status == EMBER_ZCL_STATUS_SUCCESS)
    {
        // Initialise updated value to 0
        bool updatedOnOff = false;
        status            = Attributes::OnOff::Get(endpoint, &updatedOnOff);
        if (status == EMBER_ZCL_STATUS_SUCCESS)
        {
            if (!startUpOnOff.IsNull())
            {
                switch (startUpOnOff.Value())
                {
                case OnOff::OnOffStartUpOnOff::kOff:
                    updatedOnOff = false; // Off
                    break;
                case OnOff::OnOffStartUpOnOff::kOn:
                    updatedOnOff = true; // On
                    break;
                case OnOff::OnOffStartUpOnOff::kTogglePreviousOnOff:
                    updatedOnOff = !updatedOnOff;
                    break;
                default:
                    // All other values 0x03- 0xFE are reserved - no action.
                    break;
                }
            }
            onOffValueForStartUp = updatedOnOff;
        }
    }
    return status;
}

bool OnOffServer::offCommand(const app::ConcreteCommandPath & commandPath)
{
    EmberAfStatus status = setOnOffValue(commandPath.mEndpointId, Commands::Off::Id, false);

    emberAfSendImmediateDefaultResponse(status);
    return true;
}

bool OnOffServer::onCommand(const app::ConcreteCommandPath & commandPath)
{
    EmberAfStatus status = setOnOffValue(commandPath.mEndpointId, Commands::On::Id, false);

    emberAfSendImmediateDefaultResponse(status);
    return true;
}

bool OnOffServer::toggleCommand(const app::ConcreteCommandPath & commandPath)
{
    EmberAfStatus status = setOnOffValue(commandPath.mEndpointId, Commands::Toggle::Id, false);

    emberAfSendImmediateDefaultResponse(status);
    return true;
}

bool OnOffServer::offWithEffectCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                       const Commands::OffWithEffect::DecodableType & commandData)
{
    OnOffEffectIdentifier effectId = commandData.effectId;
    uint8_t effectVariant          = commandData.effectVariant;
    chip::EndpointId endpoint      = commandPath.mEndpointId;
    EmberAfStatus status           = EMBER_ZCL_STATUS_SUCCESS;

    if (SupportsLightingApplications(endpoint))
    {
#ifdef EMBER_AF_PLUGIN_SCENES
        FabricIndex fabric = commandObj->GetAccessingFabricIndex();
#endif // EMBER_AF_PLUGIN_SCENES
        bool globalSceneControl = false;
        OnOff::Attributes::GlobalSceneControl::Get(endpoint, &globalSceneControl);

        bool isOnBeforeCommand = false;
        OnOff::Attributes::OnOff::Get(endpoint, &isOnBeforeCommand);

        if (globalSceneControl)
        {
#ifdef EMBER_AF_PLUGIN_SCENES
            GroupId groupId = ZCL_SCENES_GLOBAL_SCENE_GROUP_ID;
            if (commandObj->GetExchangeContext()->IsGroupExchangeContext())
            {
                groupId = commandObj->GetExchangeContext()->GetSessionHandle()->AsIncomingGroupSession()->GetGroupId();
            }

            emberAfScenesClusterStoreCurrentSceneCallback(fabric, endpoint, groupId, ZCL_SCENES_GLOBAL_SCENE_SCENE_ID);
#endif // EMBER_AF_PLUGIN_SCENES

            OnOff::Attributes::GlobalSceneControl::Set(endpoint, false);
            Attributes::OnTime::Set(endpoint, 0);
        }

        // Only apply effect if OnOff is on
        if (isOnBeforeCommand)
        {
            OnOffEffect * effect = inst(endpoint);

            if (effect != nullptr && effect->mOffWithEffectTrigger != nullptr)
            {
                effect->mEffectIdentifier = effectId;
                effect->mEffectVariant    = effectVariant;

                effect->mOffWithEffectTrigger(effect);
            }
        }

        status = setOnOffValue(endpoint, Commands::Off::Id, false);
    }
    else
    {
        status = EMBER_ZCL_STATUS_UNSUPPORTED_COMMAND;
    }

    emberAfSendImmediateDefaultResponse(status);
    return true;
}

bool OnOffServer::OnWithRecallGlobalSceneCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath)
{
    chip::EndpointId endpoint = commandPath.mEndpointId;
    EmberAfStatus status      = EMBER_ZCL_STATUS_SUCCESS;

    if (!SupportsLightingApplications(endpoint))
    {
        emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_UNSUPPORTED_COMMAND);
        return true;
    }

#ifdef EMBER_AF_PLUGIN_SCENES
    FabricIndex fabric = commandObj->GetAccessingFabricIndex();
#endif // EMBER_AF_PLUGIN_SCENES

    bool globalSceneControl = false;
    OnOff::Attributes::GlobalSceneControl::Get(endpoint, &globalSceneControl);

    if (globalSceneControl)
    {
        emberAfSendImmediateDefaultResponse(status);
        return true;
    }

#ifdef EMBER_AF_PLUGIN_SCENES
    GroupId groupId = ZCL_SCENES_GLOBAL_SCENE_GROUP_ID;
    if (commandObj->GetExchangeContext()->IsGroupExchangeContext())
    {
        groupId = commandObj->GetExchangeContext()->GetSessionHandle()->AsIncomingGroupSession()->GetGroupId();
    }

    emberAfScenesClusterRecallSavedSceneCallback(fabric, endpoint, groupId, ZCL_SCENES_GLOBAL_SCENE_SCENE_ID);
#endif // EMBER_AF_PLUGIN_SCENES

    OnOff::Attributes::GlobalSceneControl::Set(endpoint, true);
    setOnOffValue(endpoint, Commands::On::Id, false);

    emberAfSendImmediateDefaultResponse(status);
    return true;
}

uint32_t OnOffServer::calculateNextWaitTimeMS(void)
{
    const chip::System::Clock::Timestamp currentTime = chip::System::SystemClock().GetMonotonicTimestamp();
    chip::System::Clock::Timestamp waitTime          = UPDATE_TIME_MS;
    chip::System::Clock::Timestamp latency;

    if (currentTime > nextDesiredOnWithTimedOffTimestamp)
    {
        latency = currentTime - nextDesiredOnWithTimedOffTimestamp;
        if (latency >= UPDATE_TIME_MS)
            waitTime = chip::System::Clock::Milliseconds32(1);
        else
            waitTime -= latency;
    }

    nextDesiredOnWithTimedOffTimestamp += UPDATE_TIME_MS;

    return (uint32_t) waitTime.count();
}

bool OnOffServer::OnWithTimedOffCommand(const app::ConcreteCommandPath & commandPath,
                                        const Commands::OnWithTimedOff::DecodableType & commandData)
{
    BitFlags<OnOffControl> onOffControl = commandData.onOffControl;
    uint16_t onTime                     = commandData.onTime;
    uint16_t offWaitTime                = commandData.offWaitTime;
    EmberAfStatus status                = EMBER_ZCL_STATUS_SUCCESS;
    chip::EndpointId endpoint           = commandPath.mEndpointId;
    bool isOn                           = false;
    uint16_t currentOffWaitTime         = MAX_TIME_VALUE;
    uint16_t currentOnTime              = 0;

    EmberEventControl * event = configureEventControl(endpoint);
    VerifyOrExit(event != nullptr, status = EMBER_ZCL_STATUS_UNSUPPORTED_ENDPOINT);
    VerifyOrExit(SupportsLightingApplications(endpoint), status = EMBER_ZCL_STATUS_UNSUPPORTED_COMMAND);

    OnOff::Attributes::OnOff::Get(endpoint, &isOn);

    // OnOff is off and the commands is only accepted if on
    if (onOffControl.Has(OnOffControl::kAcceptOnlyWhenOn) && !isOn)
    {
        emberAfSendImmediateDefaultResponse(status);
        return true;
    }

    OnOff::Attributes::OffWaitTime::Get(endpoint, &currentOffWaitTime);
    OnOff::Attributes::OnTime::Get(endpoint, &currentOnTime);

    if (currentOffWaitTime > 0 && !isOn)
    {
        uint16_t newOffWaitTime = currentOffWaitTime < offWaitTime ? currentOffWaitTime : offWaitTime;
        OnOff::Attributes::OffWaitTime::Set(endpoint, newOffWaitTime);

        currentOffWaitTime = newOffWaitTime;
    }
    else
    {
        uint16_t newOnTime = currentOnTime > onTime ? currentOnTime : onTime;
        OnOff::Attributes::OnTime::Set(endpoint, newOnTime);

        OnOff::Attributes::OffWaitTime::Set(endpoint, offWaitTime);
        setOnOffValue(endpoint, Commands::On::Id, false);

        currentOnTime      = newOnTime;
        currentOffWaitTime = offWaitTime;
    }

    emberAfOnOffClusterPrintln("On Time:  %d | off wait Time: %d", currentOnTime, currentOffWaitTime);

    if (currentOnTime < MAX_TIME_VALUE && currentOffWaitTime < MAX_TIME_VALUE)
    {
        nextDesiredOnWithTimedOffTimestamp = chip::System::SystemClock().GetMonotonicTimestamp() + UPDATE_TIME_MS;
        emberEventControlSetDelayMS(configureEventControl(endpoint), (uint32_t) UPDATE_TIME_MS.count());
    }

exit:
    emberAfSendImmediateDefaultResponse(status);
    return true;
}

/**
 * @brief Updates OnOff values after timer is finished
 *
 * @param[in] endpoint endpoint associated with the finished timer
 */
void OnOffServer::updateOnOffTimeCommand(chip::EndpointId endpoint)
{
    emberAfOnOffClusterPrintln("Timer callback - Entering callbackc");

    bool isOn = false;
    OnOff::Attributes::OnOff::Get(endpoint, &isOn);

    if (isOn) // OnOff On case
    {
        // Restart Timer
        emberEventControlSetDelayMS(configureEventControl(endpoint), calculateNextWaitTimeMS());

        // Update onTime values
        uint16_t onTime = MIN_TIME_VALUE;
        OnOff::Attributes::OnTime::Get(endpoint, &onTime);
        emberAfOnOffClusterPrintln("Timer callback - On Time:  %d", onTime);

        if (onTime > 0)
        {
            onTime--;
            OnOff::Attributes::OnTime::Set(endpoint, onTime);
        }

        if (onTime == 0)
        {
            emberAfOnOffClusterPrintln("Timer callback - Turning off OnOff");

            OnOff::Attributes::OffWaitTime::Set(endpoint, 0);
            setOnOffValue(endpoint, Commands::Off::Id, false);
        }
    }
    else // OnOff Off Case
    {
        uint16_t offWaitTime = 0;
        OnOff::Attributes::OffWaitTime::Get(endpoint, &offWaitTime);

        // Validate before decreasing counter
        if (offWaitTime > 0)
        {
            offWaitTime--;
            OnOff::Attributes::OffWaitTime::Set(endpoint, offWaitTime);
        }

        emberAfOnOffClusterPrintln("Timer Callback - wait Off Time:  %d", offWaitTime);

        // Validate if necessary to restart timer
        if (offWaitTime > 0)
        {
            // Restart Timer
            emberEventControlSetDelayMS(configureEventControl(endpoint), calculateNextWaitTimeMS());
        }
        else
        {
            emberAfOnOffClusterPrintln("Timer  Callback - wait Off Time cycle finished");

            // Stop timer on the endpoint
            emberEventControlSetInactive(getEventControl(endpoint));
        }
    }
}

#ifndef IGNORE_ON_OFF_CLUSTER_START_UP_ON_OFF
bool OnOffServer::areStartUpOnOffServerAttributesNonVolatile(EndpointId endpoint)
{
    return !emberAfIsKnownVolatileAttribute(endpoint, OnOff::Id, Attributes::OnOff::Id) &&
        !emberAfIsKnownVolatileAttribute(endpoint, OnOff::Id, Attributes::StartUpOnOff::Id);
}
#endif // IGNORE_ON_OFF_CLUSTER_START_UP_ON_OFF

/**
 * @brief event control object for an endpoint
 *
 * @param[in] endpoint
 * @return EmberEventControl* configured event control
 */
EmberEventControl * OnOffServer::getEventControl(EndpointId endpoint)
{
    uint16_t index            = emberAfFindClusterServerEndpointIndex(endpoint, OnOff::Id);
    EmberEventControl * event = nullptr;

    if (index < ArraySize(eventControls))
    {
        event = &eventControls[index];
    }

    return event;
}

/**
 * @brief Configures EnventControl callback when using XY colors
 *
 * @param[in] endpoint endpoint to start timer for
 * @return EmberEventControl* configured event control
 */
EmberEventControl * OnOffServer::configureEventControl(EndpointId endpoint)
{
    EmberEventControl * controller = getEventControl(endpoint);
    VerifyOrReturnError(controller != nullptr, nullptr);

    controller->endpoint = endpoint;
    controller->callback = &onOffWaitTimeOffEventHandler;

    return controller;
}

/**********************************************************
 * OnOffEffect Implementation
 *********************************************************/

static OnOffEffect * inst(EndpointId endpoint)
{
    OnOffEffect * current = firstEffect;
    while (current != nullptr && current->mEndpoint != endpoint)
    {
        current = current->next();
    }

    return current;
}

static inline void reg(OnOffEffect * inst)
{
    inst->setNext(firstEffect);
    firstEffect = inst;
}

static inline void unreg(OnOffEffect * inst)
{
    if (firstEffect == inst)
    {
        firstEffect = firstEffect->next();
    }
    else
    {
        OnOffEffect * previous = firstEffect;
        OnOffEffect * current  = firstEffect->next();

        while (current != nullptr && current != inst)
        {
            previous = current;
            current  = current->next();
        }

        if (current != nullptr)
        {
            previous->setNext(current->next());
        }
    }
}

OnOffEffect::OnOffEffect(chip::EndpointId endpoint, OffWithEffectTriggerCommand offWithEffectTrigger,
                         OnOffEffectIdentifier effectIdentifier, uint8_t effectVariant) :
    mEndpoint(endpoint),
    mOffWithEffectTrigger(offWithEffectTrigger), mEffectIdentifier(effectIdentifier), mEffectVariant(effectVariant)
{
    reg(this);
};

OnOffEffect::~OnOffEffect()
{
    unreg(this);
};

/**********************************************************
 * Callbacks Implementation
 *********************************************************/

bool emberAfOnOffClusterOffCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                    const Commands::Off::DecodableType & commandData)
{
    return OnOffServer::Instance().offCommand(commandPath);
}

bool emberAfOnOffClusterOnCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                   const Commands::On::DecodableType & commandData)
{
    return OnOffServer::Instance().onCommand(commandPath);
}

bool emberAfOnOffClusterToggleCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                       const Commands::Toggle::DecodableType & commandData)
{
    return OnOffServer::Instance().toggleCommand(commandPath);
}

bool emberAfOnOffClusterOffWithEffectCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                              const Commands::OffWithEffect::DecodableType & commandData)
{
    return OnOffServer::Instance().offWithEffectCommand(commandObj, commandPath, commandData);
}

bool emberAfOnOffClusterOnWithRecallGlobalSceneCallback(app::CommandHandler * commandObj,
                                                        const app::ConcreteCommandPath & commandPath,
                                                        const Commands::OnWithRecallGlobalScene::DecodableType & commandData)
{
    return OnOffServer::Instance().OnWithRecallGlobalSceneCommand(commandObj, commandPath);
}

bool emberAfOnOffClusterOnWithTimedOffCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
                                               const Commands::OnWithTimedOff::DecodableType & commandData)
{
    return OnOffServer::Instance().OnWithTimedOffCommand(commandPath, commandData);
}

void emberAfOnOffClusterServerInitCallback(chip::EndpointId endpoint)
{
    OnOffServer::Instance().initOnOffServer(endpoint);
}

void onOffWaitTimeOffEventHandler(chip::EndpointId endpoint)
{
    OnOffServer::Instance().updateOnOffTimeCommand(endpoint);
}

void emberAfPluginOnOffClusterServerPostInitCallback(EndpointId endpoint) {}

void MatterOnOffPluginServerInitCallback() {}
