/*
 *
 *    Copyright (c) 2023 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/attributes/Accessors.h>
#include <app/AttributeAccessInterfaceRegistry.h>
#include <app/InteractionModelEngine.h>
#include <app/SafeAttributePersistenceProvider.h>
#include <app/clusters/mode-base-server/mode-base-server.h>
#include <app/clusters/on-off-server/on-off-server.h>
#include <app/reporting/reporting.h>
#include <app/util/attribute-storage.h>
#include <platform/DiagnosticDataProvider.h>
#include <tracing/macros.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using chip::Protocols::InteractionModel::Status;
using BootReasonType       = GeneralDiagnostics::BootReasonEnum;
using ModeOptionStructType = chip::app::Clusters::detail::Structs::ModeOptionStruct::Type;
using ModeTagStructType    = chip::app::Clusters::detail::Structs::ModeTagStruct::Type;

namespace chip {
namespace app {
namespace Clusters {
namespace ModeBase {

Instance::Instance(Delegate * aDelegate, EndpointId aEndpointId, ClusterId aClusterId, uint32_t aFeature) :
    CommandHandlerInterface(Optional<EndpointId>(aEndpointId), aClusterId),
    AttributeAccessInterface(Optional<EndpointId>(aEndpointId), aClusterId), mDelegate(aDelegate), mEndpointId(aEndpointId),
    mClusterId(aClusterId),
    mCurrentMode(0), // This is a temporary value and may not be valid. We will change this to the value of the first
                     // mode in the list at the start of the Init function to ensure that it represents a valid mode.
    mFeature(aFeature)
{
    mDelegate->SetInstance(this);
}

Instance::~Instance()
{
    Shutdown();
}

void Instance::Shutdown()
{
    if (!IsInList())
    {
        return;
    }
    UnregisterThisInstance();
    chip::app::InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this);
    unregisterAttributeAccessOverride(this);
}

CHIP_ERROR Instance::Init()
{
    // Initialise the current mode with the value of the first mode. This ensures that it is representing a valid mode.
    ReturnErrorOnFailure(mDelegate->GetModeValueByIndex(0, mCurrentMode));

    // Check if the cluster has been selected in zap
    VerifyOrDie(emberAfContainsServer(mEndpointId, mClusterId) == true);

    LoadPersistentAttributes();

    ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->RegisterCommandHandler(this));
    VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE);
    RegisterThisInstance();
    ReturnErrorOnFailure(mDelegate->Init());

    // If the StartUpMode is set, the CurrentMode attribute SHALL be set to the StartUpMode value, when the server is powered up.
    if (!mStartUpMode.IsNull())
    {
        // This behavior does not apply to reboots associated with OTA.
        // After an OTA restart, the CurrentMode attribute SHALL return to its value prior to the restart.
        // todo this only works for matter OTAs. According to the spec, this should also work for general OTAs.
        BootReasonType bootReason = BootReasonType::kUnspecified;
        CHIP_ERROR error          = DeviceLayer::GetDiagnosticDataProvider().GetBootReason(bootReason);

        if (error != CHIP_NO_ERROR)
        {
            ChipLogError(
                Zcl, "Unable to retrieve boot reason: %" CHIP_ERROR_FORMAT ". Assuming that we did not reboot because of an OTA",
                error.Format());
            bootReason = BootReasonType::kUnspecified;
        }

        if (bootReason == BootReasonType::kSoftwareUpdateCompleted)
        {
            ChipLogDetail(Zcl, "ModeBase: StartUpMode is ignored for OTA reboot.");
        }
        else
        {
            // Set CurrentMode to StartUpMode
            if (mStartUpMode.Value() != mCurrentMode)
            {
                ChipLogProgress(Zcl, "ModeBase: Changing CurrentMode to the StartUpMode value.");
                Status status = UpdateCurrentMode(mStartUpMode.Value());
                if (status != Status::Success)
                {
                    ChipLogError(Zcl, "ModeBase: Failed to change the CurrentMode to the StartUpMode value: %u",
                                 to_underlying(status));
                    return StatusIB(status).ToChipError();
                }

                ChipLogProgress(Zcl, "ModeBase: Successfully initialized CurrentMode to the StartUpMode value %u",
                                mStartUpMode.Value());
            }
        }
    }

#ifdef MATTER_DM_PLUGIN_ON_OFF_SERVER
    // OnMode with Power Up
    // If the On/Off feature is supported and the On/Off cluster attribute StartUpOnOff is present, with a
    // value of On (turn on at power up), then the CurrentMode attribute SHALL be set to the OnMode attribute
    // value when the server is supplied with power, except if the OnMode attribute is null.
    if (emberAfContainsServer(mEndpointId, OnOff::Id) &&
        emberAfContainsAttribute(mEndpointId, OnOff::Id, OnOff::Attributes::StartUpOnOff::Id) &&
        emberAfContainsAttribute(mEndpointId, mClusterId, ModeBase::Attributes::OnMode::Id) &&
        HasFeature(ModeBase::Feature::kOnOff))
    {
        DataModel::Nullable<uint8_t> onMode = GetOnMode();
        bool onOffValueForStartUp           = false;
        if (!emberAfIsKnownVolatileAttribute(mEndpointId, OnOff::Id, OnOff::Attributes::StartUpOnOff::Id) &&
            OnOffServer::Instance().getOnOffValueForStartUp(mEndpointId, onOffValueForStartUp) == Status::Success)
        {
            if (onOffValueForStartUp && !onMode.IsNull())
            {
                // Set CurrentMode to OnMode
                if (mOnMode.Value() != mCurrentMode)
                {
                    ChipLogProgress(Zcl, "ModeBase: Changing CurrentMode to the OnMode value.");
                    Status status = UpdateCurrentMode(mOnMode.Value());
                    if (status != Status::Success)
                    {
                        ChipLogError(Zcl, "ModeBase: Failed to change the CurrentMode to the OnMode value: %u",
                                     to_underlying(status));
                        return StatusIB(status).ToChipError();
                    }

                    ChipLogProgress(Zcl, "ModeBase: Successfully initialized CurrentMode to the OnMode value %u", mOnMode.Value());
                }
            }
        }
    }
#endif // MATTER_DM_PLUGIN_ON_OFF_SERVER

    return CHIP_NO_ERROR;
}

Status Instance::UpdateCurrentMode(uint8_t aNewMode)
{
    if (!IsSupportedMode(aNewMode))
    {
        return Protocols::InteractionModel::Status::ConstraintError;
    }
    uint8_t oldMode = mCurrentMode;
    mCurrentMode    = aNewMode;
    if (mCurrentMode != oldMode)
    {
        // Write new value to persistent storage.
        ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, mClusterId, Attributes::CurrentMode::Id);
        GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mCurrentMode);
        MatterReportingAttributeChangeCallback(path);
    }
    return Protocols::InteractionModel::Status::Success;
}

Status Instance::UpdateStartUpMode(DataModel::Nullable<uint8_t> aNewStartUpMode)
{
    if (!aNewStartUpMode.IsNull())
    {
        if (!IsSupportedMode(aNewStartUpMode.Value()))
        {
            return Protocols::InteractionModel::Status::ConstraintError;
        }
    }
    DataModel::Nullable<uint8_t> oldStartUpMode = mStartUpMode;
    mStartUpMode                                = aNewStartUpMode;
    if (mStartUpMode != oldStartUpMode)
    {
        // Write new value to persistent storage.
        ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, mClusterId, Attributes::StartUpMode::Id);
        GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mStartUpMode);
        MatterReportingAttributeChangeCallback(path);
    }
    return Protocols::InteractionModel::Status::Success;
}

Status Instance::UpdateOnMode(DataModel::Nullable<uint8_t> aNewOnMode)
{
    if (!aNewOnMode.IsNull())
    {
        if (!IsSupportedMode(aNewOnMode.Value()))
        {
            return Protocols::InteractionModel::Status::ConstraintError;
        }
    }
    DataModel::Nullable<uint8_t> oldOnMode = mOnMode;
    mOnMode                                = aNewOnMode;
    if (mOnMode != oldOnMode)
    {
        // Write new value to persistent storage.
        ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, mClusterId, Attributes::OnMode::Id);
        GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mOnMode);
        MatterReportingAttributeChangeCallback(path);
    }
    return Protocols::InteractionModel::Status::Success;
}

uint8_t Instance::GetCurrentMode() const
{
    return mCurrentMode;
}

DataModel::Nullable<uint8_t> Instance::GetStartUpMode() const
{
    return mStartUpMode;
}

DataModel::Nullable<uint8_t> Instance::GetOnMode() const
{
    return mOnMode;
}

void Instance::ReportSupportedModesChange()
{
    MatterReportingAttributeChangeCallback(ConcreteAttributePath(mEndpointId, mClusterId, Attributes::SupportedModes::Id));
}

bool Instance::HasFeature(Feature feature) const
{
    return (mFeature & to_underlying(feature)) != 0;
}

bool Instance::IsSupportedMode(uint8_t modeValue)
{
    uint8_t value;
    for (uint8_t i = 0; mDelegate->GetModeValueByIndex(i, value) != CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; i++)
    {
        if (value == modeValue)
        {
            return true;
        }
    }
    ChipLogDetail(Zcl, "Cannot find a mode with value %u", modeValue);
    return false;
}

CHIP_ERROR Instance::GetModeValueByModeTag(uint16_t modeTagValue, uint8_t & value)
{
    ModeTagStructType tagsBuffer[kMaxNumOfModeTags];
    DataModel::List<ModeTagStructType> mTags(tagsBuffer);
    for (uint8_t i = 0; mDelegate->GetModeTagsByIndex(i, mTags) != CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; i++)
    {
        for (size_t ii = 0; ii < mTags.size(); ii++)
        {
            if (mTags[ii].value == modeTagValue)
            {
                mDelegate->GetModeValueByIndex(i, value);
                return CHIP_NO_ERROR;
            }
        }
        mTags = tagsBuffer;
    }
    ChipLogDetail(Zcl, "Cannot find a mode with mode tag %x", modeTagValue);
    return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
}

// private methods
template <typename RequestT, typename FuncT>
void Instance::HandleCommand(HandlerContext & handlerContext, FuncT func)
{
    if (!handlerContext.mCommandHandled && (handlerContext.mRequestPath.mCommandId == RequestT::GetCommandId()))
    {
        RequestT requestPayload;

        // If the command matches what the caller is looking for, let's mark this as being handled
        // even if errors happen after this. This ensures that we don't execute any fall-back strategies
        // to handle this command since at this point, the caller is taking responsibility for handling
        // the command in its entirety, warts and all.
        //
        handlerContext.SetCommandHandled();

        if (DataModel::Decode(handlerContext.mPayload, requestPayload) != CHIP_NO_ERROR)
        {
            handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath,
                                                     Protocols::InteractionModel::Status::InvalidCommand);
            return;
        }

        func(handlerContext, requestPayload);
    }
}

// This function is called by the interaction model engine when a command destined for this instance is received.
void Instance::InvokeCommand(HandlerContext & handlerContext)
{
    switch (handlerContext.mRequestPath.mCommandId)
    {
    case ModeBase::Commands::ChangeToMode::Id:
        ChipLogDetail(Zcl, "ModeBase: Entering handling ChangeToModeWithStatus");

        HandleCommand<Commands::ChangeToMode::DecodableType>(
            handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleChangeToMode(ctx, commandData); });
    }
}

// Implements the read functionality for complex attributes.
CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
    switch (aPath.mAttributeId)
    {
    case Attributes::CurrentMode::Id:
        ReturnErrorOnFailure(aEncoder.Encode(mCurrentMode));
        break;
    case Attributes::StartUpMode::Id:
        ReturnErrorOnFailure(aEncoder.Encode(mStartUpMode));
        break;
    case Attributes::OnMode::Id:
        ReturnErrorOnFailure(aEncoder.Encode(mOnMode));
        break;
    case Attributes::FeatureMap::Id:
        ReturnErrorOnFailure(aEncoder.Encode(mFeature));
        break;
    case Attributes::SupportedModes::Id:
        Instance * d   = this;
        CHIP_ERROR err = aEncoder.EncodeList([d](const auto & encoder) -> CHIP_ERROR { return d->EncodeSupportedModes(encoder); });
        return err;
    }
    return CHIP_NO_ERROR;
}

// Implements checking before attribute writes.
CHIP_ERROR Instance::Write(const ConcreteDataAttributePath & attributePath, AttributeValueDecoder & aDecoder)
{
    DataModel::Nullable<uint8_t> newMode;
    ReturnErrorOnFailure(aDecoder.Decode(newMode));
    Status status;

    switch (attributePath.mAttributeId)
    {
    case ModeBase::Attributes::StartUpMode::Id:
        status = UpdateStartUpMode(newMode);
        return StatusIB(status).ToChipError();
    case ModeBase::Attributes::OnMode::Id:
        status = UpdateOnMode(newMode);
        return StatusIB(status).ToChipError();
    }

    return CHIP_ERROR_INCORRECT_STATE;
}

void Instance::RegisterThisInstance()
{
    if (!gModeBaseAliasesInstances.Contains(this))
    {
        gModeBaseAliasesInstances.PushBack(this);
    }
}

void Instance::UnregisterThisInstance()
{
    gModeBaseAliasesInstances.Remove(this);
}

void Instance::HandleChangeToMode(HandlerContext & ctx, const Commands::ChangeToMode::DecodableType & commandData)
{
    MATTER_TRACE_SCOPE("ChangeToMode", "ModeBase");
    uint8_t newMode = commandData.newMode;

    Commands::ChangeToModeResponse::Type response;

    // If the NewMode field doesn't match the Mode field of any entry of the SupportedModes list,
    // the ChangeToModeResponse command's Status field SHALL indicate UnsupportedMode and
    // the StatusText field SHALL be included and MAY be used to indicate the issue, with a human readable string,
    // or include an empty string.
    // We are leaving the StatusText empty since the Status is descriptive enough.
    if (!IsSupportedMode(newMode))
    {
        ChipLogError(Zcl, "ModeBase: Failed to find the option with mode %u", newMode);
        response.status = to_underlying(StatusCode::kUnsupportedMode);
        ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
        return;
    }

    // If the NewMode field is the same as the value of the CurrentMode attribute
    // the ChangeToModeResponse command SHALL have the Status field set to Success and
    // the StatusText field MAY be supplied with a human readable string or include an empty string.
    // We are leaving the StatusText empty since the Status is descriptive enough.
    if (newMode == GetCurrentMode())
    {
        response.status = to_underlying(ModeBase::StatusCode::kSuccess);
        ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
        return;
    }

    mDelegate->HandleChangeToMode(newMode, response);

    if (response.status == to_underlying(StatusCode::kSuccess))
    {
        UpdateCurrentMode(newMode);
        ChipLogProgress(Zcl, "ModeBase: HandleChangeToMode changed to mode %u", newMode);
    }

    ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
}

void Instance::LoadPersistentAttributes()
{
    // Load Current Mode
    uint8_t tempCurrentMode;
    CHIP_ERROR err = GetSafeAttributePersistenceProvider()->ReadScalarValue(
        ConcreteAttributePath(mEndpointId, mClusterId, Attributes::CurrentMode::Id), tempCurrentMode);
    if (err == CHIP_NO_ERROR)
    {
        Status status = UpdateCurrentMode(tempCurrentMode);
        if (status == Status::Success)
        {
            ChipLogDetail(Zcl, "ModeBase: Loaded CurrentMode as %u", GetCurrentMode());
        }
        else
        {
            ChipLogError(Zcl, "ModeBase: Could not update CurrentMode to %u: %u", tempCurrentMode, to_underlying(status));
        }
    }
    else
    {
        // If we cannot find the previous CurrentMode, we will assume it to be the first mode in the
        // list, as was initialised in the constructor.
        ChipLogDetail(Zcl, "ModeBase: Unable to load the CurrentMode from the KVS. Assuming %u", GetCurrentMode());
    }

    // Load Start-Up Mode
    DataModel::Nullable<uint8_t> tempStartUpMode;
    err = GetSafeAttributePersistenceProvider()->ReadScalarValue(
        ConcreteAttributePath(mEndpointId, mClusterId, Attributes::StartUpMode::Id), tempStartUpMode);
    if (err == CHIP_NO_ERROR)
    {
        Status status = UpdateStartUpMode(tempStartUpMode);
        if (status == Status::Success)
        {
            if (GetStartUpMode().IsNull())
            {
                ChipLogDetail(Zcl, "ModeBase: Loaded StartUpMode as null");
            }
            else
            {
                ChipLogDetail(Zcl, "ModeBase: Loaded StartUpMode as %u", GetStartUpMode().Value());
            }
        }
        else
        {
            ChipLogError(Zcl, "ModeBase: Could not update StartUpMode: %u", to_underlying(status));
        }
    }
    else
    {
        ChipLogDetail(Zcl, "ModeBase: Unable to load the StartUpMode from the KVS. Assuming null");
    }

    // Load On Mode
    DataModel::Nullable<uint8_t> tempOnMode;
    err = GetSafeAttributePersistenceProvider()->ReadScalarValue(
        ConcreteAttributePath(mEndpointId, mClusterId, Attributes::OnMode::Id), tempOnMode);
    if (err == CHIP_NO_ERROR)
    {
        Status status = UpdateOnMode(tempOnMode);
        if (status == Status::Success)
        {
            if (GetOnMode().IsNull())
            {
                ChipLogDetail(Zcl, "ModeBase: Loaded OnMode as null");
            }
            else
            {
                ChipLogDetail(Zcl, "ModeBase: Loaded OnMode as %u", GetOnMode().Value());
            }
        }
        else
        {
            ChipLogError(Zcl, "ModeBase: Could not update OnMode: %u", to_underlying(status));
        }
    }
    else
    {
        ChipLogDetail(Zcl, "ModeBase: Unable to load the OnMode from the KVS.      Assuming null");
    }
}

CHIP_ERROR Instance::EncodeSupportedModes(const AttributeValueEncoder::ListEncodeHelper & encoder)
{
    for (uint8_t i = 0; true; i++)
    {
        ModeOptionStructType mode;

        // Get the mode label
        char buffer[kMaxModeLabelSize];
        MutableCharSpan label(buffer);
        auto err = mDelegate->GetModeLabelByIndex(i, label);
        if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
        {
            return CHIP_NO_ERROR;
        }
        ReturnErrorOnFailure(err);

        mode.label = label;

        // Get the mode value
        ReturnErrorOnFailure(mDelegate->GetModeValueByIndex(i, mode.mode));

        // Get the mode tags
        ModeTagStructType tagsBuffer[kMaxNumOfModeTags];
        DataModel::List<ModeTagStructType> tags(tagsBuffer);
        ReturnErrorOnFailure(mDelegate->GetModeTagsByIndex(i, tags));
        mode.modeTags = tags;

        ReturnErrorOnFailure(encoder.Encode(mode));
    }
    return CHIP_NO_ERROR;
}

IntrusiveList<Instance> & GetModeBaseInstanceList()
{
    return gModeBaseAliasesInstances;
}

} // namespace ModeBase
} // namespace Clusters
} // namespace app
} // namespace chip
