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

/**
 *    @file
 *      DeviceControllerFactory is a singleton utility class that manages the
 *      runtime DeviceControllerSystemState and provides APIs to setup DeviceControllers
 *      and DeviceCommissioners.
 *
 *      Together with the SystemState this class implicitly manages the lifecycle of the underlying
 *      CHIP stack. It lazily initializes the CHIPStack when setting up Controllers if the SystemState
 *      was previously shutdown.
 */

#pragma once

#include <controller/CHIPDeviceController.h>
#include <controller/CHIPDeviceControllerSystemState.h>
#include <credentials/GroupDataProvider.h>
#include <credentials/OperationalCertificateStore.h>
#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
#include <protocols/secure_channel/SessionResumptionStorage.h>

namespace chip {

namespace Controller {

struct SetupParams
{
    OperationalCredentialsDelegate * operationalCredentialsDelegate = nullptr;

    /* The following keypair must correspond to the public key used for generating
    controllerNOC. It's used by controller to establish CASE sessions with devices */
    Crypto::P256Keypair * operationalKeypair = nullptr;

    /**
     * Controls whether or not the operationalKeypair should be owned by the
     * caller.  By default, this is false, but if the keypair cannot be
     * serialized, then setting this to true will allow the caller to manage
     * this keypair's lifecycle.
     */
    bool hasExternallyOwnedOperationalKeypair = false;

    /* The following certificates must be in x509 DER format */
    ByteSpan controllerNOC;
    ByteSpan controllerICAC;
    ByteSpan controllerRCAC;

    //
    // This must be set to a valid, operational VendorId value associated with
    // the controller/commissioner.
    //
    chip::VendorId controllerVendorId = VendorId::Unspecified;

    // The Device Pairing Delegated used to initialize a Commissioner
    DevicePairingDelegate * pairingDelegate = nullptr;

    /**
     * Controls whether we permit multiple DeviceController instances to exist
     * on the same logical fabric (identified by the tuple of the fabric's
     * root public key + fabric id).
     *
     * Each controller instance will be associated with its own FabricIndex.
     * This pivots the FabricTable to tracking identities instead of fabrics,
     * represented by FabricInfo instances that can have colliding logical fabrics.
     *
     */
    bool permitMultiControllerFabrics = false;

    //
    // Controls enabling server cluster interactions on a controller. This in turn
    // causes the following to get enabled:
    //
    //  - CASEServer to listen for unsolicited Sigma1 messages.
    //  - Advertisement of active controller operational identities.
    //
    bool enableServerInteractions = false;

    /**
     * Controls whether shutdown of the controller removes the corresponding
     * entry from the in-memory fabric table, but NOT from storage.
     *
     * Note that this means that after controller shutdown the storage and
     * in-memory versions of the fabric table will be out of sync.
     * For compatibility reasons this is the default behavior.
     *
     * @see deleteFromFabricTableOnShutdown
     */
    bool removeFromFabricTableOnShutdown = true;

    /**
     * Controls whether shutdown of the controller deletes the corresponding
     * entry from the fabric table (both in-memory and storage).
     *
     * If both `removeFromFabricTableOnShutdown` and this setting are true,
     * this setting will take precedence.
     *
     * @see removeFromFabricTableOnShutdown
     */
    bool deleteFromFabricTableOnShutdown = false;

    /**
     * Specifies whether to utilize the fabric table entry for the given FabricIndex
     * for initialization. If provided and neither the operational key pair nor the NOC
     * chain are provided, then attempt to locate a fabric corresponding to the given FabricIndex.
     */
    chip::Optional<FabricIndex> fabricIndex;

    Credentials::DeviceAttestationVerifier * deviceAttestationVerifier = nullptr;
    CommissioningDelegate * defaultCommissioner                        = nullptr;
};

// TODO everything other than the fabric storage, group data provider, OperationalKeystore,
// OperationalCertificateStore, SessionKeystore, and SessionResumptionStorage here should
// be removed. We're blocked because of the need to support !CHIP_DEVICE_LAYER
struct FactoryInitParams
{
    System::Layer * systemLayer                                        = nullptr;
    PersistentStorageDelegate * fabricIndependentStorage               = nullptr;
    Credentials::CertificateValidityPolicy * certificateValidityPolicy = nullptr;
    Credentials::GroupDataProvider * groupDataProvider                 = nullptr;
    app::reporting::ReportScheduler::TimerDelegate * timerDelegate     = nullptr;
    Crypto::SessionKeystore * sessionKeystore                          = nullptr;
    Inet::EndPointManager<Inet::TCPEndPoint> * tcpEndPointManager      = nullptr;
    Inet::EndPointManager<Inet::UDPEndPoint> * udpEndPointManager      = nullptr;
    FabricTable * fabricTable                                          = nullptr;
    Crypto::OperationalKeystore * operationalKeystore                  = nullptr;
    Credentials::OperationalCertificateStore * opCertStore             = nullptr;
    SessionResumptionStorage * sessionResumptionStorage                = nullptr;
#if CONFIG_NETWORK_LAYER_BLE
    Ble::BleLayer * bleLayer = nullptr;
#endif

    //
    // Controls enabling server cluster interactions on a controller. This in turn
    // causes the following to get enabled:
    //
    //  - Advertisement of active controller operational identities.
    //
    bool enableServerInteractions = false;

    /* The port used for operational communication to listen for and send messages over UDP/TCP.
     * The default value of `0` will pick any available port. */
    uint16_t listenPort = 0;
};

class DeviceControllerFactory
{
public:
    static DeviceControllerFactory & GetInstance()
    {
        static DeviceControllerFactory instance;
        return instance;
    }

    CHIP_ERROR Init(FactoryInitParams params);

    // Shuts down matter and frees the system state.
    //
    // Must not be called while any controllers are alive, or while any calls
    // to RetainSystemState or EnsureAndRetainSystemState have not been balanced
    // by a call to ReleaseSystemState.
    void Shutdown();

    CHIP_ERROR SetupController(SetupParams params, DeviceController & controller);
    CHIP_ERROR SetupCommissioner(SetupParams params, DeviceCommissioner & commissioner);

    // ----- IO -----
    /**
     * @brief
     * Start the event loop task within the CHIP stack
     * @return CHIP_ERROR   The return status
     */
    CHIP_ERROR ServiceEvents();

    ~DeviceControllerFactory();
    DeviceControllerFactory(DeviceControllerFactory const &) = delete;
    void operator=(DeviceControllerFactory const &)          = delete;

    //
    // Some clients do not prefer a complete shutdown of the stack being initiated if
    // all device controllers have ceased to exist. To avoid that, this method has been
    // created to permit retention of the underlying system state.
    //
    // Calls to this method must be balanced by calling ReleaseSystemState before Shutdown.
    //
    void RetainSystemState();

    //
    // To initiate shutdown of the stack upon termination of all resident controllers in the
    // system, invoke this method to decrement the refcount on the system state and consequently,
    // shut-down the stack.
    //
    // This should only be invoked if a matching call to RetainSystemState() was called prior.
    //
    // Returns true if stack was shut down in response to this call, or false otherwise.
    //
    bool ReleaseSystemState();

    // Like RetainSystemState(), but will re-initialize the system state first if necessary.
    // Calls to this method must be balanced by calling ReleaseSystemState before Shutdown.
    CHIP_ERROR EnsureAndRetainSystemState();

    //
    // Retrieve a read-only pointer to the system state object that contains pointers to key stack
    // singletons. If the pointer is null, it indicates that the DeviceControllerFactory has yet to
    // be initialized properly, or has already been shut-down.
    //
    // This pointer ceases to be valid after a call to Shutdown has been made, or if all active
    // DeviceController instances have gone to 0. Consequently, care has to be taken to correctly
    // sequence the shutting down of active controllers with any entity that interacts with objects
    // present in the system state object. If de-coupling is desired, RetainSystemState and
    // ReleaseSystemState can be used to avoid this.
    //
    const DeviceControllerSystemState * GetSystemState() const { return mSystemState; }

    class ControllerFabricDelegate final : public chip::FabricTable::Delegate
    {
    public:
        CHIP_ERROR Init(SessionResumptionStorage * sessionResumptionStorage, Credentials::GroupDataProvider * groupDataProvider)
        {
            VerifyOrReturnError(sessionResumptionStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
            VerifyOrReturnError(groupDataProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

            mSessionResumptionStorage = sessionResumptionStorage;
            mGroupDataProvider        = groupDataProvider;
            return CHIP_NO_ERROR;
        };

        void OnFabricRemoved(const chip::FabricTable & fabricTable, FabricIndex fabricIndex) override
        {
            (void) fabricTable;
            if (mGroupDataProvider != nullptr)
            {
                mGroupDataProvider->RemoveFabric(fabricIndex);
            }
            ClearCASEResumptionStateOnFabricChange(fabricIndex);
        };

        void OnFabricUpdated(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override
        {
            (void) fabricTable;
            ClearCASEResumptionStateOnFabricChange(fabricIndex);
        }

    private:
        void ClearCASEResumptionStateOnFabricChange(chip::FabricIndex fabricIndex)
        {
            VerifyOrReturn(mSessionResumptionStorage != nullptr);
            CHIP_ERROR err = mSessionResumptionStorage->DeleteAll(fabricIndex);
            if (err != CHIP_NO_ERROR)
            {
                ChipLogError(Controller,
                             "Warning, failed to delete session resumption state for fabric index 0x%x: %" CHIP_ERROR_FORMAT,
                             static_cast<unsigned>(fabricIndex), err.Format());
            }
        }

        Credentials::GroupDataProvider * mGroupDataProvider  = nullptr;
        SessionResumptionStorage * mSessionResumptionStorage = nullptr;
    };

private:
    DeviceControllerFactory() {}
    void PopulateInitParams(ControllerInitParams & controllerParams, const SetupParams & params);
    CHIP_ERROR InitSystemState(FactoryInitParams params);
    CHIP_ERROR ReinitSystemStateIfNecessary();
    void ControllerInitialized(const DeviceController & controller);

    uint16_t mListenPort;
    DeviceControllerSystemState * mSystemState                          = nullptr;
    PersistentStorageDelegate * mFabricIndependentStorage               = nullptr;
    Crypto::OperationalKeystore * mOperationalKeystore                  = nullptr;
    Credentials::OperationalCertificateStore * mOpCertStore             = nullptr;
    Credentials::CertificateValidityPolicy * mCertificateValidityPolicy = nullptr;
    SessionResumptionStorage * mSessionResumptionStorage                = nullptr;
    bool mEnableServerInteractions                                      = false;
};

} // namespace Controller
} // namespace chip
