/*
 *
 *    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.
 */

#pragma once

#include <app/icd/server/ICDServerConfig.h>
#if CHIP_CONFIG_ENABLE_ICD_SERVER
#include <app/icd/server/ICDManager.h> // nogncheck
#endif
#include <app/icd/server/ICDStateObserver.h>
#include <app/server/CommissioningModeProvider.h>
#include <credentials/FabricTable.h>
#include <lib/core/CHIPError.h>
#include <lib/core/Optional.h>
#include <lib/dnssd/Advertiser.h>
#include <platform/CHIPDeviceLayer.h>
#include <stddef.h>
#include <system/TimeSource.h>

namespace chip {
namespace app {

class DLL_EXPORT DnssdServer : public ICDStateObserver
{
public:
    static constexpr System::Clock::Timestamp kTimeoutCleared = System::Clock::kZero;

    /// Provides the system-wide implementation of the service advertiser
    static DnssdServer & Instance()
    {
        static DnssdServer instance;
        return instance;
    }

    /// Sets the secure Matter port
    void SetSecuredPort(uint16_t port) { mSecuredPort = port; }

    /// Gets the secure Matter port
    uint16_t GetSecuredPort() const { return mSecuredPort; }

    /// Sets the unsecure Matter port
    void SetUnsecuredPort(uint16_t port) { mUnsecuredPort = port; }

    /// Gets the unsecure Matter port
    uint16_t GetUnsecuredPort() const { return mUnsecuredPort; }

    /// Sets the interface id used for advertising
    void SetInterfaceId(Inet::InterfaceId interfaceId) { mInterfaceId = interfaceId; }

    /// Gets the interface id used for advertising
    Inet::InterfaceId GetInterfaceId() { return mInterfaceId; }

    //
    // Set the fabric table the DnssdServer should use for operational
    // advertising.  This must be set before StartServer() is called for the
    // first time.
    //
    void SetFabricTable(FabricTable * table)
    {
        VerifyOrDie(table != nullptr);
        mFabricTable = table;
    }

    // Set the commissioning mode provider to use.  Null provider will mean we
    // assume the commissioning mode is kDisabled.
    void SetCommissioningModeProvider(CommissioningModeProvider * provider) { mCommissioningModeProvider = provider; }

#if CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY
    /// Sets the extended discovery timeout. Value will be persisted across reboots
    void SetExtendedDiscoveryTimeoutSecs(int32_t secs);

    /// Callback from Extended Discovery Expiration timer
    /// Checks if extended discovery has expired and if so,
    /// stops commissionable node advertising
    /// Extended Discovery Expiration refers here to commissionable node advertising when NOT in commissioning mode
    void OnExtendedDiscoveryExpiration(System::Layer * aSystemLayer, void * aAppState);
#endif // CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY

#if CHIP_CONFIG_ENABLE_ICD_SERVER
    template <class AdvertisingParams>
    void AddICDKeyToAdvertisement(AdvertisingParams & advParams);

    void SetICDManager(ICDManager * manager) { mICDManager = manager; };
#endif
    /// Start operational advertising
    CHIP_ERROR AdvertiseOperational();

    /// (Re-)starts the Dnssd server, using the commissioning mode from our
    /// commissioning mode provider.
    void StartServer();

    /// (Re-)starts the Dnssd server, using the provided commissioning mode.
    void StartServer(Dnssd::CommissioningMode mode);

    //// Stop the Dnssd server.  After this call, SetFabricTable must be called
    //// again before calling StartServer().
    void StopServer();

    CHIP_ERROR GenerateRotatingDeviceId(char rotatingDeviceIdHexBuffer[], size_t rotatingDeviceIdHexBufferSize);

    /// Generates the (random) instance name that a CHIP device is to use for pre-commissioning DNS-SD
    CHIP_ERROR GetCommissionableInstanceName(char * buffer, size_t bufferLen);

    /**
     * @brief Overrides configuration so that commissionable advertisement will use an
     *        ephemeral discriminator such as one set for ECM. If the Optional has no
     *        value, the default basic discriminator is used as usual.
     *
     * @param[in] discriminator Ephemeral discriminator to override if it HasValue(), otherwise reverts
     *                          to default.
     * @return CHIP_NO_ERROR on success or CHIP_ERROR_INVALID_ARGUMENT on invalid value
     */
    CHIP_ERROR SetEphemeralDiscriminator(Optional<uint16_t> discriminator);

    // ICDStateObserver
    // No action is needed by the DnssdServer on active or idle state entries
    void OnEnterActiveMode() override{};
    void OnTransitionToIdle() override{};
    void OnICDModeChange() override;

private:
    /// Overloaded utility method for commissioner and commissionable advertisement
    /// This method is used for both commissioner discovery and commissionable node discovery since
    /// they share many fields.
    ///   commissionableNode = true : advertise commissionable node
    ///   commissionableNode = false : advertise commissioner
    CHIP_ERROR Advertise(bool commissionableNode, chip::Dnssd::CommissioningMode mode);

    /// Set MDNS commissioner advertisement
    CHIP_ERROR AdvertiseCommissioner();

    /// Set MDNS commissionable node advertisement
    CHIP_ERROR AdvertiseCommissionableNode(chip::Dnssd::CommissioningMode mode);

    // Our randomly-generated fallback "MAC address", in case we don't have a real one.
    uint8_t mFallbackMAC[chip::DeviceLayer::ConfigurationManager::kPrimaryMACAddressLength] = { 0 };

    void GetPrimaryOrFallbackMACAddress(chip::MutableByteSpan mac);

    //
    // Check if we have any valid operational credentials present in the fabric table and return true
    // if we do.
    //
    bool HaveOperationalCredentials();

    FabricTable * mFabricTable                             = nullptr;
    CommissioningModeProvider * mCommissioningModeProvider = nullptr;

#if CHIP_CONFIG_ENABLE_ICD_SERVER
    ICDManager * mICDManager = nullptr;
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER

    uint16_t mSecuredPort          = CHIP_PORT;
    uint16_t mUnsecuredPort        = CHIP_UDC_PORT;
    Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null();

    // Ephemeral discriminator to use instead of the default if set
    Optional<uint16_t> mEphemeralDiscriminator;

#if CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY
    Time::TimeSource<Time::Source::kSystem> mTimeSource;

    /// Get the current extended discovery timeout (set by
    /// SetExtendedDiscoveryTimeoutSecs, or the configuration default if not set).
    int32_t GetExtendedDiscoveryTimeoutSecs();

    /// schedule next extended discovery expiration
    CHIP_ERROR ScheduleExtendedDiscoveryExpiration();

    // mExtendedDiscoveryExpiration, if not set to kTimeoutCleared, is used to
    // indicate that we should be advertising extended discovery right now.
    System::Clock::Timestamp mExtendedDiscoveryExpiration = kTimeoutCleared;
    Optional<int32_t> mExtendedDiscoveryTimeoutSecs       = NullOptional;

    // The commissioning mode we are advertising right now.  Used to detect when
    // we need to start extended discovery advertisement.  We start this off as
    // kEnabledBasic, so that when we first start up we do extended discovery
    // advertisement if we don't enter commissioning mode.
    Dnssd::CommissioningMode mCurrentCommissioningMode = Dnssd::CommissioningMode::kEnabledBasic;
#endif // CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY
};

} // namespace app
} // namespace chip
