/*
 *
 *    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
 *      Implementation of CHIP Device Controller Factory, a utility/manager class
 *      that vends Controller objects
 */

#include <controller/CHIPDeviceControllerFactory.h>

#include <app/OperationalSessionSetup.h>
#include <app/TimerDelegates.h>
#include <app/reporting/ReportSchedulerImpl.h>
#include <app/util/DataModelHandler.h>
#include <lib/core/ErrorStr.h>
#include <messaging/ReliableMessageProtocolConfig.h>

#if CONFIG_DEVICE_LAYER
#include <platform/CHIPDeviceLayer.h>
#include <platform/ConfigurationManager.h>
#endif

#include <app/server/Dnssd.h>
#include <protocols/secure_channel/CASEServer.h>
#include <protocols/secure_channel/SimpleSessionResumptionStorage.h>

using namespace chip::Inet;
using namespace chip::System;
using namespace chip::Credentials;

namespace chip {
namespace Controller {

CHIP_ERROR DeviceControllerFactory::Init(FactoryInitParams params)
{

    // SystemState is only set the first time init is called, after that it is managed
    // internally. If SystemState is set then init has already completed.
    if (mSystemState != nullptr)
    {
        ChipLogError(Controller, "Device Controller Factory already initialized...");
        return CHIP_NO_ERROR;
    }

    // Save our initialization state that we can't recover later from a
    // created-but-shut-down system state.
    mListenPort                = params.listenPort;
    mFabricIndependentStorage  = params.fabricIndependentStorage;
    mOperationalKeystore       = params.operationalKeystore;
    mOpCertStore               = params.opCertStore;
    mCertificateValidityPolicy = params.certificateValidityPolicy;
    mSessionResumptionStorage  = params.sessionResumptionStorage;
    mEnableServerInteractions  = params.enableServerInteractions;

    CHIP_ERROR err = InitSystemState(params);

    return err;
}

CHIP_ERROR DeviceControllerFactory::ReinitSystemStateIfNecessary()
{
    VerifyOrReturnError(mSystemState != nullptr, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(mSystemState->IsShutdown(), CHIP_NO_ERROR);

    FactoryInitParams params;
    params.systemLayer        = mSystemState->SystemLayer();
    params.udpEndPointManager = mSystemState->UDPEndPointManager();
#if INET_CONFIG_ENABLE_TCP_ENDPOINT
    params.tcpEndPointManager = mSystemState->TCPEndPointManager();
#endif
#if CONFIG_NETWORK_LAYER_BLE
    params.bleLayer = mSystemState->BleLayer();
#endif
    params.listenPort                = mListenPort;
    params.fabricIndependentStorage  = mFabricIndependentStorage;
    params.enableServerInteractions  = mEnableServerInteractions;
    params.groupDataProvider         = mSystemState->GetGroupDataProvider();
    params.sessionKeystore           = mSystemState->GetSessionKeystore();
    params.fabricTable               = mSystemState->Fabrics();
    params.operationalKeystore       = mOperationalKeystore;
    params.opCertStore               = mOpCertStore;
    params.certificateValidityPolicy = mCertificateValidityPolicy;
    params.sessionResumptionStorage  = mSessionResumptionStorage;

    return InitSystemState(params);
}

CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params)
{
    if (mSystemState != nullptr)
    {
        Platform::Delete(mSystemState);
        mSystemState = nullptr;
    }

    DeviceControllerSystemStateParams stateParams;
#if CONFIG_DEVICE_LAYER
    ReturnErrorOnFailure(DeviceLayer::PlatformMgr().InitChipStack());

    stateParams.systemLayer        = &DeviceLayer::SystemLayer();
    stateParams.udpEndPointManager = DeviceLayer::UDPEndPointManager();
#if INET_CONFIG_ENABLE_TCP_ENDPOINT
    stateParams.tcpEndPointManager = DeviceLayer::TCPEndPointManager();
#endif
#else
    stateParams.systemLayer        = params.systemLayer;
    stateParams.tcpEndPointManager = params.tcpEndPointManager;
    stateParams.udpEndPointManager = params.udpEndPointManager;
    ChipLogError(Controller, "Warning: Device Controller Factory should be with a CHIP Device Layer...");
#endif // CONFIG_DEVICE_LAYER

    VerifyOrReturnError(stateParams.systemLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(stateParams.udpEndPointManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    // OperationalCertificateStore needs to be provided to init the fabric table if fabric table is
    // not provided wholesale.
    ReturnErrorCodeIf((params.fabricTable == nullptr) && (params.opCertStore == nullptr), CHIP_ERROR_INVALID_ARGUMENT);
    ReturnErrorCodeIf(params.sessionKeystore == nullptr, CHIP_ERROR_INVALID_ARGUMENT);

#if CONFIG_NETWORK_LAYER_BLE
#if CONFIG_DEVICE_LAYER
    stateParams.bleLayer = DeviceLayer::ConnectivityMgr().GetBleLayer();
#else
    stateParams.bleLayer = params.bleLayer;
#endif // CONFIG_DEVICE_LAYER
    VerifyOrReturnError(stateParams.bleLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
#endif

    stateParams.transportMgr = chip::Platform::New<DeviceTransportMgr>();

    //
    // The logic below expects IPv6 to be at index 0 of this tuple. Please do not alter that.
    //
    ReturnErrorOnFailure(stateParams.transportMgr->Init(Transport::UdpListenParameters(stateParams.udpEndPointManager)
                                                            .SetAddressType(Inet::IPAddressType::kIPv6)
                                                            .SetListenPort(params.listenPort)
#if INET_CONFIG_ENABLE_IPV4
                                                            ,
                                                        Transport::UdpListenParameters(stateParams.udpEndPointManager)
                                                            .SetAddressType(Inet::IPAddressType::kIPv4)
                                                            .SetListenPort(params.listenPort)
#endif
#if CONFIG_NETWORK_LAYER_BLE
                                                            ,
                                                        Transport::BleListenParameters(stateParams.bleLayer)
#endif
                                                            ));

    // TODO(#16231): All the new'ed state above/below in this method is never properly released or null-checked!
    stateParams.sessionMgr                = chip::Platform::New<SessionManager>();
    stateParams.certificateValidityPolicy = params.certificateValidityPolicy;
    stateParams.unsolicitedStatusHandler  = Platform::New<Protocols::SecureChannel::UnsolicitedStatusHandler>();
    stateParams.exchangeMgr               = chip::Platform::New<Messaging::ExchangeManager>();
    stateParams.messageCounterManager     = chip::Platform::New<secure_channel::MessageCounterManager>();
    stateParams.groupDataProvider         = params.groupDataProvider;
    stateParams.timerDelegate             = chip::Platform::New<chip::app::DefaultTimerDelegate>();
    stateParams.reportScheduler           = chip::Platform::New<app::reporting::ReportSchedulerImpl>(stateParams.timerDelegate);
    stateParams.sessionKeystore           = params.sessionKeystore;
    stateParams.bdxTransferServer         = chip::Platform::New<bdx::BDXTransferServer>();

    // if no fabricTable was provided, create one and track it in stateParams for cleanup
    stateParams.fabricTable = params.fabricTable;

    FabricTable * tempFabricTable = nullptr;
    if (stateParams.fabricTable == nullptr)
    {
        // TODO(#16231): Previously (and still) the objects new-ed in this entire method seem expected to last forever...
        auto newFabricTable = Platform::MakeUnique<FabricTable>();
        ReturnErrorCodeIf(!newFabricTable, CHIP_ERROR_NO_MEMORY);

        FabricTable::InitParams fabricTableInitParams;
        fabricTableInitParams.storage             = params.fabricIndependentStorage;
        fabricTableInitParams.operationalKeystore = params.operationalKeystore;
        fabricTableInitParams.opCertStore         = params.opCertStore;
        ReturnErrorOnFailure(newFabricTable->Init(fabricTableInitParams));
        stateParams.fabricTable = newFabricTable.release();
        tempFabricTable         = stateParams.fabricTable;
    }

    SessionResumptionStorage * sessionResumptionStorage;
    if (params.sessionResumptionStorage == nullptr)
    {
        auto ownedSessionResumptionStorage = chip::Platform::MakeUnique<SimpleSessionResumptionStorage>();
        ReturnErrorOnFailure(ownedSessionResumptionStorage->Init(params.fabricIndependentStorage));
        stateParams.ownedSessionResumptionStorage    = std::move(ownedSessionResumptionStorage);
        stateParams.externalSessionResumptionStorage = nullptr;
        sessionResumptionStorage                     = stateParams.ownedSessionResumptionStorage.get();
    }
    else
    {
        stateParams.ownedSessionResumptionStorage    = nullptr;
        stateParams.externalSessionResumptionStorage = params.sessionResumptionStorage;
        sessionResumptionStorage                     = stateParams.externalSessionResumptionStorage;
    }

    auto delegate = chip::Platform::MakeUnique<ControllerFabricDelegate>();
    ReturnErrorOnFailure(delegate->Init(sessionResumptionStorage, stateParams.groupDataProvider));
    stateParams.fabricTableDelegate = delegate.get();
    ReturnErrorOnFailure(stateParams.fabricTable->AddFabricDelegate(stateParams.fabricTableDelegate));
    delegate.release();

    ReturnErrorOnFailure(stateParams.sessionMgr->Init(stateParams.systemLayer, stateParams.transportMgr,
                                                      stateParams.messageCounterManager, params.fabricIndependentStorage,
                                                      stateParams.fabricTable, *stateParams.sessionKeystore));
    ReturnErrorOnFailure(stateParams.exchangeMgr->Init(stateParams.sessionMgr));
    ReturnErrorOnFailure(stateParams.messageCounterManager->Init(stateParams.exchangeMgr));
    ReturnErrorOnFailure(stateParams.unsolicitedStatusHandler->Init(stateParams.exchangeMgr));
    ReturnErrorOnFailure(stateParams.bdxTransferServer->Init(stateParams.systemLayer, stateParams.exchangeMgr));

    InitDataModelHandler();

    ReturnErrorOnFailure(Dnssd::Resolver::Instance().Init(stateParams.udpEndPointManager));

    if (params.enableServerInteractions)
    {
        stateParams.caseServer = chip::Platform::New<CASEServer>();

        // Enable listening for session establishment messages.
        ReturnErrorOnFailure(stateParams.caseServer->ListenForSessionEstablishment(
            stateParams.exchangeMgr, stateParams.sessionMgr, stateParams.fabricTable, sessionResumptionStorage,
            stateParams.certificateValidityPolicy, stateParams.groupDataProvider));

        //
        // We need to advertise the port that we're listening to for unsolicited messages over UDP. However, we have both a IPv4
        // and IPv6 endpoint to pick from. Given that the listen port passed in may be set to 0 (which then has the kernel select
        // a valid port at bind time), that will result in two possible ports being provided back from the resultant endpoint
        // initializations. Since IPv6 is POR for Matter, let's go ahead and pick that port.
        //
        app::DnssdServer::Instance().SetSecuredPort(stateParams.transportMgr->GetTransport().GetImplAtIndex<0>().GetBoundPort());

        //
        // TODO: This is a hack to workaround the fact that we have a bi-polar stack that has controller and server modalities that
        // are mutually exclusive in terms of initialization of key stack singletons. Consequently, DnssdServer accesses
        // Server::GetInstance().GetFabricTable() to access the fabric table, but we don't want to do that when we're initializing
        // the controller logic since the factory here has its own fabric table.
        //
        // Consequently, reach in set the fabric table pointer to point to the right version.
        //
        app::DnssdServer::Instance().SetFabricTable(stateParams.fabricTable);
    }

    stateParams.sessionSetupPool = Platform::New<DeviceControllerSystemStateParams::SessionSetupPool>();
    stateParams.caseClientPool   = Platform::New<DeviceControllerSystemStateParams::CASEClientPool>();

    CASEClientInitParams sessionInitParams = {
        .sessionManager            = stateParams.sessionMgr,
        .sessionResumptionStorage  = sessionResumptionStorage,
        .certificateValidityPolicy = stateParams.certificateValidityPolicy,
        .exchangeMgr               = stateParams.exchangeMgr,
        .fabricTable               = stateParams.fabricTable,
        .groupDataProvider         = stateParams.groupDataProvider,
        // Don't provide an MRP local config, so each CASE initiation will use
        // the then-current value.
        .mrpLocalConfig = NullOptional,
    };

    CASESessionManagerConfig sessionManagerConfig = {
        .sessionInitParams = sessionInitParams,
        .clientPool        = stateParams.caseClientPool,
        .sessionSetupPool  = stateParams.sessionSetupPool,
    };

    // TODO: Need to be able to create a CASESessionManagerConfig here!
    stateParams.caseSessionManager = Platform::New<CASESessionManager>();
    ReturnErrorOnFailure(stateParams.caseSessionManager->Init(stateParams.systemLayer, sessionManagerConfig));

    ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->Init(
        stateParams.exchangeMgr, stateParams.fabricTable, stateParams.reportScheduler, stateParams.caseSessionManager));

    // store the system state
    mSystemState = chip::Platform::New<DeviceControllerSystemState>(std::move(stateParams));
    mSystemState->SetTempFabricTable(tempFabricTable, params.enableServerInteractions);
    ChipLogDetail(Controller, "System State Initialized...");
    return CHIP_NO_ERROR;
}

void DeviceControllerFactory::PopulateInitParams(ControllerInitParams & controllerParams, const SetupParams & params)
{
    controllerParams.operationalCredentialsDelegate       = params.operationalCredentialsDelegate;
    controllerParams.operationalKeypair                   = params.operationalKeypair;
    controllerParams.hasExternallyOwnedOperationalKeypair = params.hasExternallyOwnedOperationalKeypair;
    controllerParams.controllerNOC                        = params.controllerNOC;
    controllerParams.controllerICAC                       = params.controllerICAC;
    controllerParams.controllerRCAC                       = params.controllerRCAC;
    controllerParams.permitMultiControllerFabrics         = params.permitMultiControllerFabrics;
    controllerParams.removeFromFabricTableOnShutdown      = params.removeFromFabricTableOnShutdown;
    controllerParams.deleteFromFabricTableOnShutdown      = params.deleteFromFabricTableOnShutdown;

    controllerParams.systemState        = mSystemState;
    controllerParams.controllerVendorId = params.controllerVendorId;

    controllerParams.enableServerInteractions = params.enableServerInteractions;
    if (params.fabricIndex.HasValue())
    {
        controllerParams.fabricIndex.SetValue(params.fabricIndex.Value());
    }
}

void DeviceControllerFactory::ControllerInitialized(const DeviceController & controller)
{
    if (mEnableServerInteractions && controller.GetFabricIndex() != kUndefinedFabricIndex)
    {
        // Restart DNS-SD advertising, because initialization of this controller could
        // have modified whether a particular fabric identity should be
        // advertised.  Just calling AdvertiseOperational() is not good enough
        // here, since we might be removing advertising.
        app::DnssdServer::Instance().StartServer();
    }
}

CHIP_ERROR DeviceControllerFactory::SetupController(SetupParams params, DeviceController & controller)
{
    VerifyOrReturnError(params.controllerVendorId != VendorId::Unspecified, CHIP_ERROR_INVALID_ARGUMENT);
    ReturnErrorOnFailure(ReinitSystemStateIfNecessary());

    ControllerInitParams controllerParams;
    PopulateInitParams(controllerParams, params);

    CHIP_ERROR err = controller.Init(controllerParams);

    if (err == CHIP_NO_ERROR)
    {
        ControllerInitialized(controller);
    }

    return err;
}

CHIP_ERROR DeviceControllerFactory::SetupCommissioner(SetupParams params, DeviceCommissioner & commissioner)
{
    VerifyOrReturnError(params.controllerVendorId != VendorId::Unspecified, CHIP_ERROR_INVALID_ARGUMENT);
    ReturnErrorOnFailure(ReinitSystemStateIfNecessary());

    CommissionerInitParams commissionerParams;

    // PopulateInitParams works against ControllerInitParams base class of CommissionerInitParams only
    PopulateInitParams(commissionerParams, params);

    // Set commissioner-specific fields not in ControllerInitParams
    commissionerParams.pairingDelegate           = params.pairingDelegate;
    commissionerParams.defaultCommissioner       = params.defaultCommissioner;
    commissionerParams.deviceAttestationVerifier = params.deviceAttestationVerifier;

    CHIP_ERROR err = commissioner.Init(commissionerParams);

    if (err == CHIP_NO_ERROR)
    {
        ControllerInitialized(commissioner);
    }

    return err;
}

CHIP_ERROR DeviceControllerFactory::ServiceEvents()
{
    VerifyOrReturnError(mSystemState != nullptr, CHIP_ERROR_INCORRECT_STATE);

#if CONFIG_DEVICE_LAYER
    ReturnErrorOnFailure(DeviceLayer::PlatformMgr().StartEventLoopTask());
#endif // CONFIG_DEVICE_LAYER

    return CHIP_NO_ERROR;
}

void DeviceControllerFactory::RetainSystemState()
{
    (void) mSystemState->Retain();
}

bool DeviceControllerFactory::ReleaseSystemState()
{
    return mSystemState->Release();
}

CHIP_ERROR DeviceControllerFactory::EnsureAndRetainSystemState()
{
    ReturnErrorOnFailure(ReinitSystemStateIfNecessary());
    RetainSystemState();
    return CHIP_NO_ERROR;
}

DeviceControllerFactory::~DeviceControllerFactory()
{
    Shutdown();
}

void DeviceControllerFactory::Shutdown()
{
    if (mSystemState != nullptr)
    {
        Platform::Delete(mSystemState);
        mSystemState = nullptr;
    }
    mFabricIndependentStorage  = nullptr;
    mOperationalKeystore       = nullptr;
    mOpCertStore               = nullptr;
    mCertificateValidityPolicy = nullptr;
    mSessionResumptionStorage  = nullptr;
}

void DeviceControllerSystemState::Shutdown()
{
    VerifyOrDie(mRefCount == 0);
    if (mHaveShutDown)
    {
        // Nothing else to do here.
        return;
    }
    mHaveShutDown = true;

    ChipLogDetail(Controller, "Shutting down the System State, this will teardown the CHIP Stack");

    if (mTempFabricTable && mEnableServerInteractions)
    {
        // The DnssdServer is holding a reference to our temp fabric table,
        // which we are about to destroy.  Stop it, so that it will stop trying
        // to use it.
        app::DnssdServer::Instance().StopServer();
    }

    if (mFabricTableDelegate != nullptr)
    {
        if (mFabrics != nullptr)
        {
            mFabrics->RemoveFabricDelegate(mFabricTableDelegate);
        }

        chip::Platform::Delete(mFabricTableDelegate);
        mFabricTableDelegate = nullptr;
    }

    if (mBDXTransferServer != nullptr)
    {
        mBDXTransferServer->Shutdown();
        chip::Platform::Delete(mBDXTransferServer);
        mBDXTransferServer = nullptr;
    }

    if (mCASEServer != nullptr)
    {
        mCASEServer->Shutdown();
        chip::Platform::Delete(mCASEServer);
        mCASEServer = nullptr;
    }

    if (mCASESessionManager != nullptr)
    {
        mCASESessionManager->Shutdown();
        Platform::Delete(mCASESessionManager);
        mCASESessionManager = nullptr;
    }

    // mCASEClientPool and mSessionSetupPool must be deallocated
    // after mCASESessionManager, which uses them.

    if (mSessionSetupPool != nullptr)
    {
        Platform::Delete(mSessionSetupPool);
        mSessionSetupPool = nullptr;
    }

    if (mCASEClientPool != nullptr)
    {
        Platform::Delete(mCASEClientPool);
        mCASEClientPool = nullptr;
    }

    Dnssd::Resolver::Instance().Shutdown();

    // Shut down the interaction model
    app::InteractionModelEngine::GetInstance()->Shutdown();

    // Shut down the TransportMgr. This holds Inet::UDPEndPoints so it must be shut down
    // before PlatformMgr().Shutdown() shuts down Inet.
    if (mTransportMgr != nullptr)
    {
        mTransportMgr->Close();
        chip::Platform::Delete(mTransportMgr);
        mTransportMgr = nullptr;
    }

    if (mExchangeMgr != nullptr)
    {
        mExchangeMgr->Shutdown();
    }
    if (mSessionMgr != nullptr)
    {
        mSessionMgr->Shutdown();
    }

    mSystemLayer        = nullptr;
    mUDPEndPointManager = nullptr;
#if INET_CONFIG_ENABLE_TCP_ENDPOINT
    mTCPEndPointManager = nullptr;
#endif
#if CONFIG_NETWORK_LAYER_BLE
    mBleLayer = nullptr;
#endif // CONFIG_NETWORK_LAYER_BLE

    if (mMessageCounterManager != nullptr)
    {
        chip::Platform::Delete(mMessageCounterManager);
        mMessageCounterManager = nullptr;
    }

    if (mExchangeMgr != nullptr)
    {
        chip::Platform::Delete(mExchangeMgr);
        mExchangeMgr = nullptr;
    }

    if (mUnsolicitedStatusHandler != nullptr)
    {
        Platform::Delete(mUnsolicitedStatusHandler);
        mUnsolicitedStatusHandler = nullptr;
    }

    if (mSessionMgr != nullptr)
    {
        chip::Platform::Delete(mSessionMgr);
        mSessionMgr = nullptr;
    }

    if (mReportScheduler != nullptr)
    {
        chip::Platform::Delete(mReportScheduler);
        mReportScheduler = nullptr;
    }

    if (mTimerDelegate != nullptr)
    {
        chip::Platform::Delete(mTimerDelegate);
        mTimerDelegate = nullptr;
    }

    if (mTempFabricTable != nullptr)
    {
        mTempFabricTable->Shutdown();
        chip::Platform::Delete(mTempFabricTable);
        mTempFabricTable = nullptr;
        // if we created a temp fabric table, then mFabrics points to it.
        // if we did not create a temp fabric table, then keep the reference
        // so that SetupController/Commissioner can use it
        mFabrics = nullptr;
    }

#if CONFIG_DEVICE_LAYER
    //
    // We can safely call PlatformMgr().Shutdown(), which like DeviceController::Shutdown(),
    // expects to be called with external thread synchronization and will not try to acquire the
    // stack lock.
    //
    // Actually stopping the event queue is a separable call that applications will have to sequence.
    // Consumers are expected to call PlaformMgr().StopEventLoopTask() before calling
    // DeviceController::Shutdown() in the CONFIG_DEVICE_LAYER configuration
    //
    DeviceLayer::PlatformMgr().Shutdown();
#endif
}

} // namespace Controller
} // namespace chip
