/*
 *
 *    Copyright (c) 2025 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
 *      This file implements System::Layer dedicated to Zephyr RTOS, which does not use select().
 */

#include <lib/support/CodeUtils.h>
#include <platform/LockTracker.h>
#include <system/PlatformEventSupport.h>
#include <system/SystemFaultInjection.h>
#include <system/SystemLayer.h>
#include <system/SystemLayerImplZephyr.h>

namespace chip {
namespace System {

LayerImplZephyr::LayerImplZephyr() {}

CriticalFailure LayerImplZephyr::Init()
{
    VerifyOrReturnError(mLayerState.SetInitializing(), CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(mLayerState.SetInitialized(), CHIP_ERROR_INCORRECT_STATE);

    return CHIP_NO_ERROR;
}

void LayerImplZephyr::Shutdown()
{
    mLayerState.ResetFromInitialized();
}

CriticalFailure LayerImplZephyr::StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState)
{
    assertChipStackLockedByCurrentThread();

    VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

    CHIP_SYSTEM_FAULT_INJECT(FaultInjection::kFault_TimeoutImmediate, delay = System::Clock::kZero);

    CancelTimer(onComplete, appState);

    TimerList::Node * timer = mTimerPool.Create(*this, SystemClock().GetMonotonicTimestamp() + delay, onComplete, appState);
    VerifyOrReturnError(timer != nullptr, CHIP_ERROR_NO_MEMORY);

    if (mTimerList.Add(timer) == timer)
    {
        // The new timer is the earliest, so the time until the next event has probably changed.
        TriggerPlatformTimerUpdate();
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR LayerImplZephyr::ExtendTimerTo(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState)
{
    VerifyOrReturnError(delay.count() > 0, CHIP_ERROR_INVALID_ARGUMENT);

    assertChipStackLockedByCurrentThread();

    Clock::Timeout remainingTime = mTimerList.GetRemainingTime(onComplete, appState);
    if (remainingTime.count() < delay.count())
    {
        return StartTimer(delay, onComplete, appState);
    }

    return CHIP_NO_ERROR;
}

bool LayerImplZephyr::IsTimerActive(TimerCompleteCallback onComplete, void * appState)
{
    bool timerIsActive = (mTimerList.GetRemainingTime(onComplete, appState) > Clock::kZero);

    if (!timerIsActive)
    {
        // check if the timer is in the mExpiredTimers list about to be fired.
        for (TimerList::Node * timer = mExpiredTimers.Earliest(); timer != nullptr; timer = timer->mNextTimer)
        {
            if (timer->GetCallback().GetOnComplete() == onComplete && timer->GetCallback().GetAppState() == appState)
            {
                return true;
            }
        }
    }

    return timerIsActive;
}

Clock::Timeout LayerImplZephyr::GetRemainingTime(TimerCompleteCallback onComplete, void * appState)
{
    return mTimerList.GetRemainingTime(onComplete, appState);
}

void LayerImplZephyr::CancelTimer(TimerCompleteCallback onComplete, void * appState)
{
    assertChipStackLockedByCurrentThread();

    VerifyOrReturn(mLayerState.IsInitialized());

    TimerList::Node * timer = mTimerList.Remove(onComplete, appState);
    if (timer == nullptr)
    {
        // The timer was not in our "will fire in the future" list, but it might
        // be in the "we're about to fire these" chunk we already grabbed from
        // that list.  Check for it there too, and if found there we still want
        // to cancel it.
        timer = mExpiredTimers.Remove(onComplete, appState);
    }

    VerifyOrReturn(timer != nullptr);
    mTimerPool.Release(timer);
}

CriticalFailure LayerImplZephyr::ScheduleWork(TimerCompleteCallback onComplete, void * appState)
{
    assertChipStackLockedByCurrentThread();

    VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

    // Ideally we would not use a timer here at all, but if we try to just
    // ScheduleLambda the lambda needs to capture the following:
    // 1) onComplete
    // 2) appState
    // 3) The `this` pointer, because onComplete needs to be passed a pointer to
    //    the System::Layer.
    //
    // On a 64-bit system that's 24 bytes, but lambdas passed to ScheduleLambda
    // are capped at CHIP_CONFIG_LAMBDA_EVENT_SIZE which is 16 bytes.
    //
    // So for now use a timer as a poor-man's closure that captures `this` and
    // onComplete and appState in a single pointer, so we fit inside the size
    // limit.
    //
    // TODO: We could do something here where we compile-time condition on the
    // sizes of things and use a direct ScheduleLambda if it would fit and this
    // setup otherwise.
    //
    // TODO: But also, unit tests seem to do SystemLayer::ScheduleWork without
    // actually running a useful event loop (in the PlatformManager sense),
    // which breaks if we use ScheduleLambda here, since that does rely on the
    // PlatformManager event loop. So for now, keep scheduling an expires-ASAP
    // timer, but just make sure we don't cancel existing timers with the same
    // callback and appState, so ScheduleWork invocations don't stomp on each
    // other.
    TimerList::Node * timer = mTimerPool.Create(*this, SystemClock().GetMonotonicTimestamp(), onComplete, appState);
    VerifyOrReturnError(timer != nullptr, CHIP_ERROR_NO_MEMORY);

    if (mTimerList.Add(timer) == timer)
    {
        // The new timer is the earliest, so the time until the next event has probably changed.
        TriggerPlatformTimerUpdate();
    }

    return CHIP_NO_ERROR;
}

void LayerImplZephyr::TriggerPlatformTimerUpdate()
{
    CHIP_ERROR status = PlatformEventing::StartTimer(*this, Clock::kZero);
    if (status != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Error starting platform timer: %" CHIP_ERROR_FORMAT, status.Format());
    }
}

/**
 * Get the next awaken time from the timer list.
 *
 * @return The next awaken time or nullopt if there are no timers in the list.
 */
std::optional<Clock::Timestamp> LayerImplZephyr::GetNextAwakenTime()
{
    TimerList::Node * timer = mTimerList.Earliest();
    if (timer)
    {
        return timer->AwakenTime();
    }

    return std::nullopt;
}

/**
 * Handle the platform timer expiration event. Completes any timers that have expired.
 *
 * A static API that gets called when the platform timer expires. Any expired timers are completed and removed from the list
 * of active timers in the layer object.
 *
 * It is assumed that this API is called only while on the thread which owns the CHIP System Layer object.
 *
 * @note
 *      It's harmless if this API gets called and there are no expired timers.
 *
 *  @return CHIP_NO_ERROR on success, error code otherwise.
 *
 */
CHIP_ERROR LayerImplZephyr::HandlePlatformTimer()
{
    VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

    // Obtain the list of currently expired timers. Any new timers added by timer callback are NOT handled on this pass,
    // since that could result in infinite handling of new timers blocking any other progress.
    VerifyOrDieWithMsg(mExpiredTimers.Empty(), DeviceLayer, "Re-entry into HandleEvents from a timer callback?");
    Clock::Timestamp now    = SystemClock().GetMonotonicTimestamp();
    mExpiredTimers          = mTimerList.ExtractEarlier(Clock::Timeout(1) + now);
    TimerList::Node * timer = nullptr;
    while ((timer = mExpiredTimers.PopEarliest()) != nullptr)
    {
        mTimerPool.Invoke(timer);
    }

    return CHIP_NO_ERROR;
}

} // namespace System
} // namespace chip
