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

// This file contains an implementation of the OTARequestorDriver interface class.
// Individual platforms may supply their own implementations of OTARequestorDriver
// or use this one. There are no requirements or assumptions on the implementation other
// than adherence to the OTA Image Update Requestor part of the Matter specification; the
// aspects of the functionality not mandated by the specification are considered implementation choices.
//
// This particular implementation of the OTARequestorDriver makes the following choices:
// - Only a single timer can be active at any given moment
// - The periodic query timer is running if and only if there is no update in progress (the core logic
//   UpdateState is kIdle)
// - AnnounceOTAProviders command is ignored if an update is in progress
// - The provider location passed in AnnounceOTAProviders is used in a single query (possibly retried) and then discarded
// - Explicitly triggering a query through TriggerImmediateQuery() cancels any in-progress update
// - A QueryImage call results in the driver iterating through the list of default OTA providers, from beginning to the end, until a
//   provider successfully transfers the OTA image. If a provider is busy, it will be retried a set number of times before moving
//   to the next available one. If all else fails, the periodic query timer is kicked off again.

#include <platform/CHIPDeviceLayer.h>
#include <platform/OTAImageProcessor.h>

#include "DefaultOTARequestorDriver.h"
#include "OTARequestorInterface.h"

#include <app/AppConfig.h>

namespace chip {
namespace DeviceLayer {
namespace {

using namespace app::Clusters::OtaSoftwareUpdateRequestor;
using namespace app::Clusters::OtaSoftwareUpdateRequestor::Structs;

constexpr uint8_t kMaxInvalidSessionRetries        = 1;  // Max # of query image retries to perform on invalid session error
constexpr uint32_t kDelayQueryUponCommissioningSec = 30; // Delay before sending the initial image query after commissioning
constexpr uint32_t kImmediateStartDelaySec         = 1;  // Delay before sending a query in response to UrgentUpdateAvailable

#if NON_SPEC_COMPLIANT_OTA_ACTION_DELAY_FLOOR >= 0
constexpr System::Clock::Seconds32 kDefaultDelayedActionTime = System::Clock::Seconds32(NON_SPEC_COMPLIANT_OTA_ACTION_DELAY_FLOOR);
#else
constexpr System::Clock::Seconds32 kDefaultDelayedActionTime = System::Clock::Seconds32(120);
#endif // NON_SPEC_COMPLIANT_OTA_ACTION_DELAY_FLOOR

DefaultOTARequestorDriver * ToDriver(void * context)
{
    return static_cast<DefaultOTARequestorDriver *>(context);
}

} // namespace

void DefaultOTARequestorDriver::Init(OTARequestorInterface * requestor, OTAImageProcessorInterface * processor)
{
    mRequestor                = requestor;
    mImageProcessor           = processor;
    mProviderRetryCount       = 0;
    mInvalidSessionRetryCount = 0;

    if (mImageProcessor->IsFirstImageRun())
    {
        SystemLayer().ScheduleLambda([this] {
            CHIP_ERROR error = mImageProcessor->ConfirmCurrentImage();

            if (error != CHIP_NO_ERROR)
            {
                ChipLogError(SoftwareUpdate, "Failed to confirm image: %" CHIP_ERROR_FORMAT, error.Format());
                mRequestor->Reset();
                return;
            }

            if (mSendNotifyUpdateApplied)
            {
                mRequestor->NotifyUpdateApplied();
            }
        });
    }
    else if ((mRequestor->GetCurrentUpdateState() != OTAUpdateStateEnum::kIdle))
    {
        // Not running a new image for the first time but also not in the idle state may indicate there is a problem
        mRequestor->Reset();
    }
    else
    {
        // Start the first periodic query timer
        StartSelectedTimer(SelectedTimer::kPeriodicQueryTimer);
    }
}

bool DefaultOTARequestorDriver::CanConsent()
{
    return false;
}

uint16_t DefaultOTARequestorDriver::GetMaxDownloadBlockSize()
{
    return maxDownloadBlockSize;
}

void DefaultOTARequestorDriver::SetMaxDownloadBlockSize(uint16_t blockSize)
{
    maxDownloadBlockSize = blockSize;
}

void StartDelayTimerHandler(System::Layer * systemLayer, void * appState)
{
    ToDriver(appState)->SendQueryImage();
}

bool DefaultOTARequestorDriver::ProviderLocationsEqual(const ProviderLocationType & a, const ProviderLocationType & b)
{
    if ((a.fabricIndex == b.fabricIndex) && (a.providerNodeID == b.providerNodeID) && (a.endpoint == b.endpoint))
    {
        return true;
    }

    return false;
}

void DefaultOTARequestorDriver::HandleIdleStateExit()
{
    // Start watchdog timer to monitor new Query Image session
    StartSelectedTimer(SelectedTimer::kWatchdogTimer);
}

void DefaultOTARequestorDriver::HandleIdleStateEnter(IdleStateReason reason)
{
    if (reason != IdleStateReason::kInvalidSession)
    {
        mInvalidSessionRetryCount = 0;
    }

    switch (reason)
    {
    case IdleStateReason::kUnknown:
        ChipLogProgress(SoftwareUpdate, "Unknown idle state reason so set the periodic timer for a next attempt");
        StartSelectedTimer(SelectedTimer::kPeriodicQueryTimer);
        break;
    case IdleStateReason::kIdle:
        // There is no current OTA update in progress so start the periodic query timer
        StartSelectedTimer(SelectedTimer::kPeriodicQueryTimer);
        break;
    case IdleStateReason::kInvalidSession:
        if (mInvalidSessionRetryCount < kMaxInvalidSessionRetries)
        {
            // An invalid session is detected which may be temporary (such as provider being restarted)
            // so try to query the same provider again. Since the session has already been disconnected prior to
            // getting here, this new query should trigger an attempt to re-establish CASE. If that subsequently fails,
            // we conclusively know the provider is not available, and will fall into the else clause below on that attempt.
            SendQueryImage();
            mInvalidSessionRetryCount++;
        }
        else
        {
            mInvalidSessionRetryCount = 0;
            StartSelectedTimer(SelectedTimer::kPeriodicQueryTimer);
        }
        break;
    }
}

void DefaultOTARequestorDriver::DownloadUpdateTimerHandler(System::Layer * systemLayer, void * appState)
{
    DefaultOTARequestorDriver * driver = ToDriver(appState);

    VerifyOrDie(driver->mRequestor != nullptr);
    driver->mRequestor->DownloadUpdate();
}

void DefaultOTARequestorDriver::ApplyUpdateTimerHandler(System::Layer * systemLayer, void * appState)
{
    DefaultOTARequestorDriver * driver = ToDriver(appState);

    VerifyOrDie(driver->mRequestor != nullptr);
    driver->mRequestor->ApplyUpdate();
}

void DefaultOTARequestorDriver::ApplyTimerHandler(System::Layer * systemLayer, void * appState)
{
    DefaultOTARequestorDriver * driver = ToDriver(appState);

    VerifyOrDie(driver->mImageProcessor != nullptr);

    if (driver->mImageProcessor->Apply() != CHIP_NO_ERROR)
    {
        driver->mRequestor->CancelImageUpdate();
    }
}

void DefaultOTARequestorDriver::UpdateAvailable(const UpdateDescription & update, System::Clock::Seconds32 delay)
{
    // IMPLEMENTATION CHOICE:
    // This implementation unconditionally downloads an available update

    VerifyOrDie(mRequestor != nullptr);
    ScheduleDelayedAction(delay, DownloadUpdateTimerHandler, this);
}

CHIP_ERROR DefaultOTARequestorDriver::UpdateNotFound(UpdateNotFoundReason reason, System::Clock::Seconds32 delay)
{
    CHIP_ERROR status = CHIP_NO_ERROR;

    switch (reason)
    {
    case UpdateNotFoundReason::kUpToDate:
        break;
    case UpdateNotFoundReason::kBusy: {
        status = ScheduleQueryRetry(true, chip::max(kDefaultDelayedActionTime, delay));
        if (status == CHIP_ERROR_MAX_RETRY_EXCEEDED)
        {
            // If max retry exceeded with current provider, try a different provider
            status = ScheduleQueryRetry(false, chip::max(kDefaultDelayedActionTime, delay));
        }
        break;
    }
    case UpdateNotFoundReason::kNotAvailable: {
        // Schedule a query only if a different provider is available
        status = ScheduleQueryRetry(false, chip::max(kDefaultDelayedActionTime, delay));
        break;
    }
    }
    return status;
}

void DefaultOTARequestorDriver::UpdateDownloaded()
{
    VerifyOrDie(mRequestor != nullptr);
    mRequestor->ApplyUpdate();
}

void DefaultOTARequestorDriver::UpdateConfirmed(System::Clock::Seconds32 delay)
{
    VerifyOrDie(mImageProcessor != nullptr);
    ScheduleDelayedAction(delay, ApplyTimerHandler, this);
}

void DefaultOTARequestorDriver::UpdateSuspended(System::Clock::Seconds32 delay)
{
    VerifyOrDie(mRequestor != nullptr);

    if (delay < kDefaultDelayedActionTime)
    {
        delay = kDefaultDelayedActionTime;
    }

    ScheduleDelayedAction(delay, ApplyUpdateTimerHandler, this);
}

void DefaultOTARequestorDriver::UpdateDiscontinued()
{
    VerifyOrDie(mImageProcessor != nullptr);
    mImageProcessor->Abort();

    // Cancel all update timers
    UpdateCancelled();
}

// Cancel all OTA update timers
void DefaultOTARequestorDriver::UpdateCancelled()
{
    // Cancel all OTA Update timers started by OTARequestorDriver regardless of whether thery are running or not
    CancelDelayedAction(DownloadUpdateTimerHandler, this);
    CancelDelayedAction(StartDelayTimerHandler, this);
    CancelDelayedAction(ApplyTimerHandler, this);
    CancelDelayedAction(ApplyUpdateTimerHandler, this);
}

void DefaultOTARequestorDriver::ScheduleDelayedAction(System::Clock::Seconds32 delay, System::TimerCompleteCallback action,
                                                      void * aAppState)
{
    VerifyOrDie(SystemLayer().StartTimer(std::chrono::duration_cast<System::Clock::Timeout>(delay), action, aAppState) ==
                CHIP_NO_ERROR);
}

void DefaultOTARequestorDriver::CancelDelayedAction(System::TimerCompleteCallback action, void * aAppState)
{
    SystemLayer().CancelTimer(action, aAppState);
}

// Device commissioning has completed, schedule a provider query
void DefaultOTARequestorDriver::OTACommissioningCallback()
{
    // Schedule a query. At the end of this query/update process the Default Provider timer is started
    ScheduleDelayedAction(System::Clock::Seconds32(kDelayQueryUponCommissioningSec), StartDelayTimerHandler, this);
}

void DefaultOTARequestorDriver::ProcessAnnounceOTAProviders(
    const ProviderLocationType & providerLocation,
    app::Clusters::OtaSoftwareUpdateRequestor::OTAAnnouncementReason announcementReason)
{
    // If reason is URGENT_UPDATE_AVAILABLE, we start OTA immediately. Otherwise, respect the timer value set in mOtaStartDelaySec.
    // This is done to exemplify what a real-world OTA Requestor might do while also being configurable enough to use as a test app.
    uint32_t secToStart = 0;
    switch (announcementReason)
    {
    case OTAAnnouncementReason::kSimpleAnnouncement:
    case OTAAnnouncementReason::kUpdateAvailable:
        secToStart = mOtaStartDelaySec;
        break;
    case OTAAnnouncementReason::kUrgentUpdateAvailable:
        // TODO: Implement random delay per spec
        secToStart = kImmediateStartDelaySec;
        break;
    default:
        ChipLogError(SoftwareUpdate, "Unexpected announcementReason: %u", static_cast<uint8_t>(announcementReason));
        return;
    }

    // IMPLEMENTATION CHOICE:
    // This implementation of the OTARequestor driver ignores the announcement if an update is in progress,
    // otherwise it queries the provider passed in the announcement

    if (mRequestor->GetCurrentUpdateState() != OTAUpdateStateEnum::kIdle)
    {
        ChipLogProgress(SoftwareUpdate, "State is not kIdle, ignoring the AnnounceOTAProviders. State: %d",
                        (int) mRequestor->GetCurrentUpdateState());
        return;
    }

    // Point to the announced provider
    mRequestor->SetCurrentProviderLocation(providerLocation);

    ScheduleDelayedAction(System::Clock::Seconds32(secToStart), StartDelayTimerHandler, this);
}

void DefaultOTARequestorDriver::SendQueryImage()
{
    OTAUpdateStateEnum currentUpdateState;
    Optional<ProviderLocationType> lastUsedProvider;
    mRequestor->GetProviderLocation(lastUsedProvider);
    if (!lastUsedProvider.HasValue())
    {
        ProviderLocationType providerLocation;
        bool listExhausted = false;
        if (GetNextProviderLocation(providerLocation, listExhausted) == true)
        {
            mRequestor->SetCurrentProviderLocation(providerLocation);
        }
        else
        {
            ChipLogProgress(SoftwareUpdate, "No provider available");
            return;
        }
    }

    currentUpdateState = mRequestor->GetCurrentUpdateState();
    if ((currentUpdateState == OTAUpdateStateEnum::kIdle) || (currentUpdateState == OTAUpdateStateEnum::kDelayedOnQuery))
    {
        mProviderRetryCount++;
        DeviceLayer::SystemLayer().ScheduleLambda([this] { mRequestor->TriggerImmediateQueryInternal(); });
    }
    else
    {
        ChipLogProgress(SoftwareUpdate, "Query already in progress");
    }
}

void DefaultOTARequestorDriver::PeriodicQueryTimerHandler(System::Layer * systemLayer, void * appState)
{
    ChipLogProgress(SoftwareUpdate, "Default Provider timer handler is invoked");

    DefaultOTARequestorDriver * driver = ToDriver(appState);

    // Determine which provider to query next
    ProviderLocationType providerLocation;
    bool listExhausted = false;
    if (driver->GetNextProviderLocation(providerLocation, listExhausted) != true)
    {
        driver->StartSelectedTimer(SelectedTimer::kPeriodicQueryTimer);
        return;
    }

    driver->mRequestor->SetCurrentProviderLocation(providerLocation);

    driver->SendQueryImage();
}

void DefaultOTARequestorDriver::StartPeriodicQueryTimer()
{
    ChipLogProgress(SoftwareUpdate, "Starting the periodic query timer, timeout: %u seconds",
                    (unsigned int) mPeriodicQueryTimeInterval);
    ScheduleDelayedAction(System::Clock::Seconds32(mPeriodicQueryTimeInterval), PeriodicQueryTimerHandler, this);
}

void DefaultOTARequestorDriver::StopPeriodicQueryTimer()
{
    ChipLogProgress(SoftwareUpdate, "Stopping the Periodic Query timer");
    CancelDelayedAction(PeriodicQueryTimerHandler, this);
}

void DefaultOTARequestorDriver::RekickPeriodicQueryTimer()
{
    ChipLogProgress(SoftwareUpdate, "Rekicking the Periodic Query timer");
    StopPeriodicQueryTimer();
    StartPeriodicQueryTimer();
}

void DefaultOTARequestorDriver::WatchdogTimerHandler(System::Layer * systemLayer, void * appState)
{
    DefaultOTARequestorDriver * driver = ToDriver(appState);

    ChipLogError(SoftwareUpdate, "Watchdog timer detects state stuck at %u. Cancelling download and resetting state.",
                 to_underlying(driver->mRequestor->GetCurrentUpdateState()));

    // Something went wrong and OTA requestor is stuck in a non-idle state for too long.
    // Let's just cancel download, reset state, and re-start periodic query timer.
    driver->UpdateDiscontinued();
    driver->mRequestor->CancelImageUpdate();
    driver->StartPeriodicQueryTimer();
}

void DefaultOTARequestorDriver::StartWatchdogTimer()
{
    ChipLogProgress(SoftwareUpdate, "Starting the watchdog timer, timeout: %u seconds", (unsigned int) mWatchdogTimeInterval);
    ScheduleDelayedAction(System::Clock::Seconds32(mWatchdogTimeInterval), WatchdogTimerHandler, this);
}

void DefaultOTARequestorDriver::StopWatchdogTimer()
{
    ChipLogProgress(SoftwareUpdate, "Stopping the watchdog timer");
    CancelDelayedAction(WatchdogTimerHandler, this);
}

void DefaultOTARequestorDriver::StartSelectedTimer(SelectedTimer timer)
{
    switch (timer)
    {
    case SelectedTimer::kPeriodicQueryTimer:
        StopWatchdogTimer();
        StartPeriodicQueryTimer();
        break;
    case SelectedTimer::kWatchdogTimer:
        StopPeriodicQueryTimer();
        StartWatchdogTimer();
        break;
    }
}

/**
 * Returns the next available Provider location. The algorithm is to simply loop through the list of DefaultOtaProviders as a
 * circular list and return the next value (based on the last used provider). If the list of DefaultOtaProviders is empty, FALSE is
 * returned.
 */
bool DefaultOTARequestorDriver::GetNextProviderLocation(ProviderLocationType & providerLocation, bool & listExhausted)
{
    Optional<ProviderLocationType> lastUsedProvider;
    mRequestor->GetProviderLocation(lastUsedProvider);
    mProviderRetryCount = 0; // Reset provider retry count
    listExhausted       = false;

    // Iterate through the default providers list and find the last used provider. If found, return the provider after it
    auto iterator = mRequestor->GetDefaultOTAProviderListIterator();
    while (lastUsedProvider.HasValue() && iterator.Next())
    {
        if (ProviderLocationsEqual(iterator.GetValue(), lastUsedProvider.Value()))
        {
            if (iterator.Next())
            {
                providerLocation = iterator.GetValue();
                return true;
            }
        }
    }

    // If no suitable candidate found, return the first element of the default providers list or an error
    iterator = mRequestor->GetDefaultOTAProviderListIterator();
    if (iterator.Next())
    {
        providerLocation = iterator.GetValue();
        listExhausted    = true;
        return true;
    }

    ChipLogError(SoftwareUpdate, "No suitable OTA Provider candidate found");
    return false;
}

CHIP_ERROR DefaultOTARequestorDriver::ScheduleQueryRetry(bool trySameProvider, System::Clock::Seconds32 delay)
{
    CHIP_ERROR status = CHIP_NO_ERROR;

    if (trySameProvider == false)
    {
        VerifyOrDie(mRequestor != nullptr);

        ProviderLocationType providerLocation;
        bool listExhausted = false;

        // Note that the "listExhausted" being set to TRUE, implies that the entire list of
        // defaultOTAProviders has been traversed. On bootup, the last provider is reset
        // which ensures that every QueryImage call will ensure that the list is traversed from
        // start to end, until an OTA is successfully completed.
        if ((GetNextProviderLocation(providerLocation, listExhausted) != true) || (listExhausted == true))
        {
            status = CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
        }
        else
        {
            mRequestor->SetCurrentProviderLocation(providerLocation);
        }
    }

    if (mProviderRetryCount > kMaxBusyProviderRetryCount)
    {
        ChipLogProgress(SoftwareUpdate, "Max retry of %u exceeded.  Will not retry", kMaxBusyProviderRetryCount);
        status = CHIP_ERROR_MAX_RETRY_EXCEEDED;
    }

    if (status == CHIP_NO_ERROR)
    {
        ChipLogProgress(SoftwareUpdate, "Scheduling a retry; delay: %" PRIu32, delay.count());
        ScheduleDelayedAction(delay, StartDelayTimerHandler, this);
    }

    return status;
}

} // namespace DeviceLayer
} // namespace chip
