/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2016-2017 Nest Labs, Inc.
 *    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.
 */

/**
 * @file
 *
 * @brief
 *   Class declarations for a monotonically-increasing counter that is periodically
 *   saved to the provided storage.
 */

#pragma once

#include <lib/core/CHIPEncoding.h>
#include <lib/core/CHIPPersistentStorageDelegate.h>
#include <lib/support/CHIPCounter.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/DefaultStorageKeyAllocator.h>
#include <limits>

namespace chip {

/**
 * @class PersistedCounter
 *
 * @brief
 *   A class for managing a counter as an integer value intended to persist
 *   across reboots.
 *
 * Counter values are always set to start at a multiple of a bootup value
 * "epoch".
 *
 * Example:
 *
 * - Assuming epoch is 100 via PersistedCounter::Init(_, 100) and GetValue +
 *   AdvanceValue is called, we get the following outputs:
 *
 *   - Output: 0, 1, 2, 3, 4  <reboot/reinit>
 *   - Output: 100, 101, 102, 103, 104, 105 <reboot/reinit>
 *   - Output: 200, 201, 202, ...., 299, 300, 301, 302 <reboot/reinit>
 *   - Output: 400, 401 ...
 *
 */
template <typename T>
class PersistedCounter : public MonotonicallyIncreasingCounter<T>
{
public:
    PersistedCounter() : mKey(StorageKeyName::Uninitialized()) {}
    ~PersistedCounter() override {}

    /**
     *  @brief
     *    Initialize a PersistedCounter object.
     *
     *  @param[in] aStorage the storage to use for the counter values.
     *  @param[in] aKey the key to use for storing the counter values.
     *  @param[in] aEpoch  On bootup, values we vend will start at a
     *                     multiple of this parameter.
     *
     *  @return CHIP_ERROR_INVALID_ARGUMENT if aStorageDelegate or aKey is NULL
     *          CHIP_ERROR_INVALID_INTEGER_VALUE if aEpoch is 0.
     *          CHIP_NO_ERROR otherwise
     */
    CHIP_ERROR Init(PersistentStorageDelegate * aStorage, StorageKeyName aKey, T aEpoch)
    {
        VerifyOrReturnError(aStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
        VerifyOrReturnError(aKey.IsInitialized(), CHIP_ERROR_INVALID_ARGUMENT);
        VerifyOrReturnError(aEpoch > 0, CHIP_ERROR_INVALID_INTEGER_VALUE);

        mStorage = aStorage;
        mKey     = aKey;
        mEpoch   = aEpoch;

        T startValue;

        // Read our previously-stored starting value.
        ReturnErrorOnFailure(ReadStartValue(startValue));

#if CHIP_CONFIG_PERSISTED_COUNTER_DEBUG_LOGGING
        if constexpr (std::is_same_v<decltype(startValue), uint64_t>)
        {
            ChipLogDetail(EventLogging, "PersistedCounter::Init() aEpoch 0x" ChipLogFormatX64 " startValue 0x" ChipLogFormatX64,
                          ChipLogValueX64(aEpoch), ChipLogValueX64(startValue));
        }
        else if (std::is_same_v<decltype(startValue), uint32_t>)
        {
            ChipLogDetail(EventLogging, "PersistedCounter::Init() aEpoch 0x%" PRIx32 " startValue 0x%" PRIx32,
                          static_cast<uint32_t>(aEpoch), static_cast<uint32_t>(startValue));
        }
#endif

        ReturnErrorOnFailure(PersistNextEpochStart(static_cast<T>(startValue + aEpoch)));

        // This will set the starting value, after which we're ready.
        return MonotonicallyIncreasingCounter<T>::Init(startValue);
    }

    /**
     *  @brief Increment the counter by N and write to persisted storage if we've completed the current epoch.
     *
     *  @param value value of N
     *
     *  @return Any error returned by a write to persisted storage.
     */
    CHIP_ERROR AdvanceBy(T value) override
    {
        VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
        VerifyOrReturnError(mKey.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

        // If value is 0, we do not need to do anything
        VerifyOrReturnError(value > 0, CHIP_NO_ERROR);

        // We should update the persisted epoch value if :
        // 1- Sum of the current counter and value is greater or equal to the mNextEpoch.
        //    This is the standard operating case.
        // 2- Increasing the current counter by value would cause a roll over. This would cause the current value to be < to the
        //    mNextEpoch so we force an update.
        bool shouldDoEpochUpdate = ((MonotonicallyIncreasingCounter<T>::GetValue() + value) >= mNextEpoch) ||
            (MonotonicallyIncreasingCounter<T>::GetValue() > std::numeric_limits<T>::max() - value);

        ReturnErrorOnFailure(MonotonicallyIncreasingCounter<T>::AdvanceBy(value));

        if (shouldDoEpochUpdate)
        {
            // Since AdvanceBy allows the counter to be increased by an arbitrary value, it is possible that the new counter value
            // is greater than mNextEpoch + mEpoch. As such, we want the next Epoch value to be calculated from the new current
            // value.
            PersistAndVerifyNextEpochStart(MonotonicallyIncreasingCounter<T>::GetValue());
        }

        return CHIP_NO_ERROR;
    }

    /**
     *  @brief Increment the counter and write to persisted storage if we've completed the current epoch.
     *
     *  @return Any error returned by a write to persisted storage.
     */
    CHIP_ERROR Advance() override
    {
        VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
        VerifyOrReturnError(mKey.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

        ReturnErrorOnFailure(MonotonicallyIncreasingCounter<T>::Advance());

        if (MonotonicallyIncreasingCounter<T>::GetValue() >= mNextEpoch)
        {
            ReturnErrorOnFailure(PersistAndVerifyNextEpochStart(mNextEpoch));
        }

        return CHIP_NO_ERROR;
    }

private:
    CHIP_ERROR PersistAndVerifyNextEpochStart(T refEpoch)
    {
        // Value advanced past the previously persisted "start point".
        // Ensure that a new starting point is persisted.
        ReturnErrorOnFailure(PersistNextEpochStart(static_cast<T>(refEpoch + mEpoch)));

        // Advancing the epoch should have ensured that the current value is valid
        VerifyOrReturnError(static_cast<T>(MonotonicallyIncreasingCounter<T>::GetValue() + mEpoch) == mNextEpoch,
                            CHIP_ERROR_INTERNAL);

        // Previous check did not take into consideration that the counter value can be equal to the max counter value or
        // rollover.
        // TODO(#33175): PersistedCounter allows rollover so this check is incorrect. We need a Counter class that adequatly
        // manages rollover behavior for counters that cannot rollover.
        // VerifyOrReturnError(MonotonicallyIncreasingCounter<T>::GetValue() < mNextEpoch, CHIP_ERROR_INTERNAL);

        return CHIP_NO_ERROR;
    }

    /**
     *  @brief
     *    Write out the counter value to persistent storage.
     *
     *  @param[in] aStartValue  The counter value to write out.
     *
     *  @return Any error returned by a write to persistent storage.
     */
    CHIP_ERROR
    PersistNextEpochStart(T aStartValue)
    {
        mNextEpoch = aStartValue;
#if CHIP_CONFIG_PERSISTED_COUNTER_DEBUG_LOGGING
        if constexpr (std::is_same_v<decltype(aStartValue), uint64_t>)
        {
            ChipLogDetail(EventLogging, "PersistedCounter::WriteStartValue() aStartValue 0x" ChipLogFormatX64,
                          ChipLogValueX64(aStartValue));
        }
        else
        {
            ChipLogDetail(EventLogging, "PersistedCounter::WriteStartValue() aStartValue 0x%" PRIx32,
                          static_cast<uint32_t>(aStartValue));
        }
#endif

        T valueLE = Encoding::LittleEndian::HostSwap<T>(aStartValue);
        return mStorage->SyncSetKeyValue(mKey.KeyName(), &valueLE, sizeof(valueLE));
    }

    /**
     *  @brief
     *    Read our starting counter value (if we have one) in from persistent storage.
     *
     *  @param[in,out] aStartValue  The value read out.
     *
     *  @return Any error returned by a read from persistent storage.
     */
    CHIP_ERROR ReadStartValue(T & aStartValue)
    {
        T valueLE     = GetInitialCounterValue();
        uint16_t size = sizeof(valueLE);

        VerifyOrReturnError(mKey.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

        CHIP_ERROR err = mStorage->SyncGetKeyValue(mKey.KeyName(), &valueLE, size);
        if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
        {
            // No previously-stored value, no worries, the counter is initialized to zero.
            // Suppress the error.
            err = CHIP_NO_ERROR;
        }
        else
        {
            // TODO: Figure out how to avoid a bootloop here.  Maybe we should just
            // init to 0?  Or a random value?
            ReturnErrorOnFailure(err);
        }

        if (size != sizeof(valueLE))
        {
            // TODO: Again, figure out whether this could lead to bootloops.
            return CHIP_ERROR_INCORRECT_STATE;
        }

        aStartValue = Encoding::LittleEndian::HostSwap<T>(valueLE);

#if CHIP_CONFIG_PERSISTED_COUNTER_DEBUG_LOGGING
        if constexpr (std::is_same_v<decltype(aStartValue), uint64_t>)
        {
            ChipLogDetail(EventLogging, "PersistedCounter::ReadStartValue() aStartValue 0x" ChipLogFormatX64,
                          ChipLogValueX64(aStartValue));
        }
        else
        {
            ChipLogDetail(EventLogging, "PersistedCounter::ReadStartValue() aStartValue 0x%" PRIx32,
                          static_cast<uint32_t>(aStartValue));
        }
#endif

        return CHIP_NO_ERROR;
    }

    /**
     * @brief Get the Initial Counter Value
     *
     * By default, persisted counters start off at 0.
     */
    virtual inline T GetInitialCounterValue() { return 0; }

    PersistentStorageDelegate * mStorage = nullptr; // start value is stored here
    StorageKeyName mKey;
    T mEpoch     = 0; // epoch modulus value
    T mNextEpoch = 0; // next epoch start
};

} // namespace chip
