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

#pragma once

#include <lib/core/CHIPError.h>
#include <lib/core/CHIPPersistentStorageDelegate.h>
#include <lib/core/DataModelTypes.h>
#include <lib/support/BitFlags.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ScopedBuffer.h>

#include "OperationalCertificateStore.h"

namespace chip {
namespace Credentials {

/**
 * @brief OperationalCertificateStore implementation making use of PersistentStorageDelegate
 *        to load/store certificates. This is the legacy behavior of `FabricTable` prior
 *        to refactors to use `OperationalCertificateStore` and exists as a baseline example
 *        of how to use the interface.
 */
class PersistentStorageOpCertStore final : public OperationalCertificateStore
{
public:
    PersistentStorageOpCertStore() {}
    virtual ~PersistentStorageOpCertStore() { Finish(); }

    // Non-copyable
    PersistentStorageOpCertStore(PersistentStorageOpCertStore const &) = delete;
    void operator=(PersistentStorageOpCertStore const &)               = delete;

    /**
     * @brief Initialize the certificate store to map to a given storage delegate.
     *
     * @param storage Pointer to persistent storage delegate to use. Must outlive this instance.
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_INCORRECT_STATE if already initialized
     */
    CHIP_ERROR Init(PersistentStorageDelegate * storage)
    {
        VerifyOrReturnError(mStorage == nullptr, CHIP_ERROR_INCORRECT_STATE);
        RevertPendingOpCerts();
        mStorage = storage;
        return CHIP_NO_ERROR;
    }

    /**
     * @brief Finalize the certificate store, so that subsequent operations fail
     */
    void Finish()
    {
        VerifyOrReturn(mStorage != nullptr);

        RevertPendingOpCerts();
        mStorage = nullptr;
    }

    bool HasPendingRootCert() const override;
    bool HasPendingNocChain() const override;

    bool HasCertificateForFabric(FabricIndex fabricIndex, CertChainElement element) const override;

    CHIP_ERROR AddNewTrustedRootCertForFabric(FabricIndex fabricIndex, const ByteSpan & rcac) override;
    CHIP_ERROR AddNewOpCertsForFabric(FabricIndex fabricIndex, const ByteSpan & noc, const ByteSpan & icac) override;
    CHIP_ERROR UpdateOpCertsForFabric(FabricIndex fabricIndex, const ByteSpan & noc, const ByteSpan & icac) override;

    CHIP_ERROR CommitOpCertsForFabric(FabricIndex fabricIndex) override;
    CHIP_ERROR RemoveOpCertsForFabric(FabricIndex fabricIndex) override;

    void RevertPendingOpCertsExceptRoot() override
    {
        mPendingIcac.Free();
        mPendingNoc.Free();

        if (mPendingRcac.Get() == nullptr)
        {
            mPendingFabricIndex = kUndefinedFabricIndex;
        }
        mStateFlags.Clear(StateFlags::kAddNewOpCertsCalled);
        mStateFlags.Clear(StateFlags::kUpdateOpCertsCalled);
    }

    void RevertPendingOpCerts() override
    {
        RevertPendingOpCertsExceptRoot();

        // Clear the rest statelessly
        mPendingRcac.Free();
        mPendingFabricIndex = kUndefinedFabricIndex;
        mStateFlags.ClearAll();
    }

    CHIP_ERROR GetCertificate(FabricIndex fabricIndex, CertChainElement element, MutableByteSpan & outCertificate) const override;

protected:
    enum class StateFlags : uint8_t
    {
        // Below are flags to assist interlock logic
        kAddNewOpCertsCalled     = (1u << 0),
        kAddNewTrustedRootCalled = (1u << 1),
        kUpdateOpCertsCalled     = (1u << 2),
    };

    // Returns CHIP_ERROR_NOT_FOUND if a pending certificate couldn't be found, otherwise status of pending copy
    CHIP_ERROR GetPendingCertificate(FabricIndex fabricIndex, CertChainElement element, MutableByteSpan & outCertificate) const;

    // Returns true if any pending or persisted state exists for the fabricIndex, false if nothing at all is found.
    bool HasAnyCertificateForFabric(FabricIndex fabricIndex) const;

    PersistentStorageDelegate * mStorage = nullptr;

    // This pending fabric index is `kUndefinedFabricIndex` if there are no pending certs at all for the fabric
    FabricIndex mPendingFabricIndex = kUndefinedFabricIndex;

    Platform::ScopedMemoryBufferWithSize<uint8_t> mPendingRcac;
    Platform::ScopedMemoryBufferWithSize<uint8_t> mPendingIcac;
    Platform::ScopedMemoryBufferWithSize<uint8_t> mPendingNoc;

    BitFlags<StateFlags> mStateFlags;
};

} // namespace Credentials
} // namespace chip
