/*
 *
 *    Copyright (c) 2022 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.
 */

/**
 *    @file
 *          Provides the implementation of the FailSafeContext object.
 */

#include <lib/support/SafeInt.h>
#include <platform/CHIPDeviceConfig.h>
#include <platform/ConnectivityManager.h>
#include <platform/internal/CHIPDeviceLayerInternal.h>

#include "FailSafeContext.h"

using namespace chip::DeviceLayer;

namespace chip {
namespace app {

void FailSafeContext::HandleArmFailSafeTimer(System::Layer * layer, void * aAppState)
{
    FailSafeContext * failSafeContext = reinterpret_cast<FailSafeContext *>(aAppState);
    failSafeContext->FailSafeTimerExpired();
}

void FailSafeContext::HandleMaxCumulativeFailSafeTimer(System::Layer * layer, void * aAppState)
{
    FailSafeContext * failSafeContext = reinterpret_cast<FailSafeContext *>(aAppState);
    failSafeContext->FailSafeTimerExpired();
}

void FailSafeContext::HandleDisarmFailSafe(intptr_t arg)
{
    FailSafeContext * failSafeContext = reinterpret_cast<FailSafeContext *>(arg);
    failSafeContext->DisarmFailSafe();
}

void FailSafeContext::SetFailSafeArmed(bool armed)
{
#if CHIP_DEVICE_CONFIG_ENABLE_SED
    if (IsFailSafeArmed() != armed)
    {
        // Per spec, we should be staying in active mode while a fail-safe is
        // armed.
        DeviceLayer::ConnectivityMgr().RequestSEDActiveMode(armed);
    }
#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
#if CHIP_CONFIG_ENABLE_ICD_SERVER
    if (IsFailSafeArmed() != armed)
    {
        DeviceLayer::ChipDeviceEvent event;
        event.Type                = DeviceLayer::DeviceEventType::kFailSafeStateChanged;
        event.FailSafeState.armed = armed;
        CHIP_ERROR err            = DeviceLayer::PlatformMgr().PostEvent(&event);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(AppServer, "Failed to post kFailSafeStateChanged event %" CHIP_ERROR_FORMAT, err.Format());
        }
    }
#endif
    mFailSafeArmed = armed;
}

void FailSafeContext::FailSafeTimerExpired()
{
    if (!IsFailSafeArmed())
    {
        // In case this was a pending timer event in event loop, and we had
        // done CommissioningComplete or manual disarm.
        return;
    }

    ChipLogProgress(FailSafe, "Fail-safe timer expired");
    ScheduleFailSafeCleanup(mFabricIndex, mAddNocCommandHasBeenInvoked, mUpdateNocCommandHasBeenInvoked);
}

void FailSafeContext::ScheduleFailSafeCleanup(FabricIndex fabricIndex, bool addNocCommandInvoked, bool updateNocCommandInvoked)
{
    // Not armed, but busy so cannot rearm (via General Commissioning cluster) until the flushing
    // via `HandleDisarmFailSafe` path is complete.
    // TODO: This is hacky and we need to remove all this event pushing business, to keep all fail-safe logic-only.
    mFailSafeBusy = true;

    SetFailSafeArmed(false);

    ChipDeviceEvent event;
    event.Type                                                = DeviceEventType::kFailSafeTimerExpired;
    event.FailSafeTimerExpired.fabricIndex                    = fabricIndex;
    event.FailSafeTimerExpired.addNocCommandHasBeenInvoked    = addNocCommandInvoked;
    event.FailSafeTimerExpired.updateNocCommandHasBeenInvoked = updateNocCommandInvoked;
    CHIP_ERROR status                                         = PlatformMgr().PostEvent(&event);

    if (status != CHIP_NO_ERROR)
    {
        ChipLogError(FailSafe, "Failed to post fail-safe timer expired: %" CHIP_ERROR_FORMAT, status.Format());
    }

    PlatformMgr().ScheduleWork(HandleDisarmFailSafe, reinterpret_cast<intptr_t>(this));
}

CHIP_ERROR FailSafeContext::ArmFailSafe(FabricIndex accessingFabricIndex, System::Clock::Seconds16 expiryLengthSeconds)
{
    VerifyOrReturnError(!IsFailSafeBusy(), CHIP_ERROR_INCORRECT_STATE);

    CHIP_ERROR err           = CHIP_NO_ERROR;
    bool cancelTimersIfError = false;
    if (!IsFailSafeArmed())
    {
        System::Clock::Timeout maxCumulativeTimeout = System::Clock::Seconds32(CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC);
        SuccessOrExit(err = DeviceLayer::SystemLayer().StartTimer(maxCumulativeTimeout, HandleMaxCumulativeFailSafeTimer, this));
        cancelTimersIfError = true;
    }

    SuccessOrExit(
        err = DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(expiryLengthSeconds), HandleArmFailSafeTimer, this));

    SetFailSafeArmed(true);
    mFabricIndex = accessingFabricIndex;

exit:

    if (err != CHIP_NO_ERROR && cancelTimersIfError)
    {
        DeviceLayer::SystemLayer().CancelTimer(HandleArmFailSafeTimer, this);
        DeviceLayer::SystemLayer().CancelTimer(HandleMaxCumulativeFailSafeTimer, this);
    }
    return err;
}

void FailSafeContext::DisarmFailSafe()
{
    DeviceLayer::SystemLayer().CancelTimer(HandleArmFailSafeTimer, this);
    DeviceLayer::SystemLayer().CancelTimer(HandleMaxCumulativeFailSafeTimer, this);

    ResetState();

    ChipLogProgress(FailSafe, "Fail-safe cleanly disarmed");
}

void FailSafeContext::ForceFailSafeTimerExpiry()
{
    if (!IsFailSafeArmed())
    {
        return;
    }

    // Cancel the timer since we force its action
    DeviceLayer::SystemLayer().CancelTimer(HandleArmFailSafeTimer, this);
    DeviceLayer::SystemLayer().CancelTimer(HandleMaxCumulativeFailSafeTimer, this);

    FailSafeTimerExpired();
}

} // namespace app
} // namespace chip
