/*
 *
 *    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
 *      This file defines objects for a User-Directed Commissioning unsolicited
 *      initiator (client) and recipient (server).
 *
 */

#pragma once

#include "UDCClients.h"
#include <lib/core/CHIPCore.h>
#include <lib/dnssd/Resolver.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/DLLUtil.h>
#include <lib/support/logging/CHIPLogging.h>
#include <messaging/ExchangeContext.h>
#include <messaging/ExchangeMgr.h>
#include <messaging/Flags.h>
#include <protocols/Protocols.h>
#include <transport/TransportMgr.h>

namespace chip {
namespace Protocols {
namespace UserDirectedCommissioning {

inline constexpr char kProtocolName[] = "UserDirectedCommissioning";

// Cache contains 16 clients. This may need to be tweaked.
inline constexpr uint8_t kMaxUDCClients = 16;

/**
 * User Directed Commissioning Protocol Message Types
 */
enum class MsgType : uint8_t
{
    IdentificationDeclaration = 0x00,
};

/**
 * Represents the Identification Delaration message
 * sent by a UDC client to a UDC server.
 *
 * ### IdentificationDeclaration format
 *
 * <pre>
 *  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
 *  ┃ instance name '\n'        ┃ ignore   ┃ additional data TLV ┃
 *  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━┛
 *  │← · · kInstanceNameMaxLength + 1 · · →│← TLV DataLength()  →│
 *
 * Commissioning kInstanceNameMaxLength is 16
 * </pre>
 *
 */
class DLL_EXPORT IdentificationDeclaration
{
public:
    constexpr static size_t kUdcTLVDataMaxBytes = 500;

    const char * GetInstanceName() const { return mInstanceName; }
    void SetInstanceName(const char * instanceName) { Platform::CopyString(mInstanceName, instanceName); }

    bool HasDiscoveryInfo() { return mVendorId != 0 && mProductId != 0 && mCdPort != 0 && strlen(mDeviceName) > 0; }

    const char * GetDeviceName() const { return mDeviceName; }
    void SetDeviceName(const char * deviceName) { Platform::CopyString(mDeviceName, deviceName); }

    uint16_t GetCdPort() const { return mCdPort; }
    void SetCdPort(uint16_t port) { mCdPort = port; }

    uint16_t GetVendorId() const { return mVendorId; }
    void SetVendorId(uint16_t vendorId) { mVendorId = vendorId; }

    uint16_t GetProductId() const { return mProductId; }
    void SetProductId(uint16_t productId) { mProductId = productId; }

    const uint8_t * GetRotatingId() const { return mRotatingId; }
    size_t GetRotatingIdLength() const { return mRotatingIdLen; }
    void SetRotatingId(const uint8_t * rotatingId, size_t rotatingIdLen)
    {
        size_t maxSize = ArraySize(mRotatingId);
        mRotatingIdLen = (maxSize < rotatingIdLen) ? maxSize : rotatingIdLen;
        memcpy(mRotatingId, rotatingId, mRotatingIdLen);
    }

    bool GetTargetAppInfo(uint8_t index, TargetAppInfo & info) const
    {
        if (index < mNumTargetAppInfos)
        {
            info.vendorId  = mTargetAppInfos[index].vendorId;
            info.productId = mTargetAppInfos[index].productId;
            return true;
        }
        return false;
    }
    uint8_t GetNumTargetAppInfos() const { return mNumTargetAppInfos; }

    bool AddTargetAppInfo(TargetAppInfo vid)
    {
        if (mNumTargetAppInfos >= sizeof(mTargetAppInfos))
        {
            // already at max
            return false;
        }
        mTargetAppInfos[mNumTargetAppInfos].vendorId  = vid.vendorId;
        mTargetAppInfos[mNumTargetAppInfos].productId = vid.productId;
        mNumTargetAppInfos++;
        return true;
    }

    const char * GetPairingInst() const { return mPairingInst; }
    void SetPairingInst(const char * pairingInst) { Platform::CopyString(mPairingInst, pairingInst); }

    uint16_t GetPairingHint() const { return mPairingHint; }
    void SetPairingHint(uint16_t pairingHint) { mPairingHint = pairingHint; }

    void SetNoPasscode(bool newValue) { mNoPasscode = newValue; };
    bool GetNoPasscode() const { return mNoPasscode; };

    void SetCdUponPasscodeDialog(bool newValue) { mCdUponPasscodeDialog = newValue; };
    bool GetCdUponPasscodeDialog() const { return mCdUponPasscodeDialog; };

    void SetCommissionerPasscode(bool newValue) { mCommissionerPasscode = newValue; };
    bool GetCommissionerPasscode() const { return mCommissionerPasscode; };

    void SetCommissionerPasscodeReady(bool newValue) { mCommissionerPasscodeReady = newValue; };
    bool GetCommissionerPasscodeReady() const { return mCommissionerPasscodeReady; };

    void SetCancelPasscode(bool newValue) { mCancelPasscode = newValue; };
    bool GetCancelPasscode() const { return mCancelPasscode; };

    /**
     *  Writes the IdentificationDeclaration message to the given buffer.
     *
     * @return Total number of bytes written or 0 if an error occurred.
     */
    uint32_t WritePayload(uint8_t * payloadBuffer, size_t payloadBufferSize);

    /**
     *  Reads the IdentificationDeclaration message from the given buffer.
     */
    CHIP_ERROR ReadPayload(uint8_t * payloadBuffer, size_t payloadBufferSize);

    /**
     *  Assigns fields from this Identification Declaration to the given UDC client state.
     */
    void UpdateClientState(UDCClientState * client)
    {
        client->SetDeviceName(GetDeviceName());
        client->SetVendorId(GetVendorId());
        client->SetProductId(GetProductId());
        client->SetRotatingId(GetRotatingId(), GetRotatingIdLength());
        client->SetPairingInst(GetPairingInst());
        client->SetPairingHint(GetPairingHint());
        for (uint8_t i = 0; i < GetNumTargetAppInfos(); i++)
        {
            TargetAppInfo info;
            if (GetTargetAppInfo(i, info))
            {
                client->AddTargetAppInfo(info);
            }
        }

        client->SetCdPort(GetCdPort());
        client->SetNoPasscode(GetNoPasscode());
        client->SetCdUponPasscodeDialog(GetCdUponPasscodeDialog());
        client->SetCommissionerPasscode(GetCommissionerPasscode());
        client->SetCommissionerPasscodeReady(GetCommissionerPasscodeReady());
        client->SetCancelPasscode(GetCancelPasscode());
    }

    void DebugLog()
    {
        ChipLogDetail(AppServer, "---- Identification Declaration Start ----");

        ChipLogDetail(AppServer, "\tinstance: %s", mInstanceName);
        if (strlen(mDeviceName) != 0)
        {
            ChipLogDetail(AppServer, "\tdevice Name: %s", mDeviceName);
        }
        if (mVendorId != 0)
        {
            ChipLogDetail(AppServer, "\tvendor id: %d", mVendorId);
        }
        if (mProductId != 0)
        {
            ChipLogDetail(AppServer, "\tproduct id: %d", mProductId);
        }
        if (mCdPort != 0)
        {
            ChipLogDetail(AppServer, "\tcd port: %d", mCdPort);
        }
        if (mRotatingIdLen > 0)
        {
            char rotatingIdString[chip::Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
            Encoding::BytesToUppercaseHexString(mRotatingId, mRotatingIdLen, rotatingIdString, sizeof(rotatingIdString));
            ChipLogDetail(AppServer, "\trotating id: %s", rotatingIdString);
        }
        for (uint8_t i = 0; i < mNumTargetAppInfos; i++)
        {
            ChipLogDetail(AppServer, "\tapp vendor id / product id [%d]: %u/%u", i, mTargetAppInfos[i].vendorId,
                          mTargetAppInfos[i].productId);
        }
        if (strlen(mPairingInst) != 0)
        {
            ChipLogDetail(AppServer, "\tpairing instruction: %s", mPairingInst);
        }
        if (mPairingHint != 0)
        {
            ChipLogDetail(AppServer, "\tpairing hint: %d", mPairingHint);
        }

        if (mNoPasscode)
        {
            ChipLogDetail(AppServer, "\tno passcode: true");
        }
        if (mCdUponPasscodeDialog)
        {
            ChipLogDetail(AppServer, "\tcd upon passcode dialog: true");
        }
        if (mCommissionerPasscode)
        {
            ChipLogDetail(AppServer, "\tcommissioner passcode: true");
        }
        if (mCommissionerPasscodeReady)
        {
            ChipLogDetail(AppServer, "\tcommissioner passcode ready: true");
        }
        if (mCancelPasscode)
        {
            ChipLogDetail(AppServer, "\tcancel passcode: true");
        }
        ChipLogDetail(AppServer, "---- Identification Declaration End ----");
    }

private:
    // TODO: update spec per the latest tags
    enum IdentificationDeclarationTLVTag
    {
        kVendorIdTag = 1,
        kProductIdTag,
        kDeviceNameTag,
        kDeviceTypeTag,
        kPairingInstTag,
        kPairingHintTag,
        kRotatingIdTag,
        kCdPortTag,
        kTargetAppListTag,
        kTargetAppTag,
        kAppVendorIdTag,
        kAppProductIdTag,
        kNoPasscodeTag,
        kCdUponPasscodeDialogTag,
        kCommissionerPasscodeTag,
        kCommissionerPasscodeReadyTag,
        kCancelPasscodeTag,

        kMaxNum = UINT8_MAX
    };

    char mInstanceName[Dnssd::Commission::kInstanceNameMaxLength + 1] = {};
    char mDeviceName[Dnssd::kMaxDeviceNameLen + 1]                    = {};
    uint16_t mCdPort                                                  = 0;

    uint16_t mVendorId  = 0;
    uint16_t mProductId = 0;
    uint8_t mRotatingId[chip::Dnssd::kMaxRotatingIdLen];
    size_t mRotatingIdLen = 0;

    constexpr static size_t kMaxTargetAppInfos = 10;
    uint8_t mNumTargetAppInfos                 = 0; // number of vendor Ids
    TargetAppInfo mTargetAppInfos[kMaxTargetAppInfos];

    char mPairingInst[chip::Dnssd::kMaxPairingInstructionLen + 1] = {};
    uint16_t mPairingHint                                         = 0;

    bool mNoPasscode                = false;
    bool mCdUponPasscodeDialog      = false;
    bool mCommissionerPasscode      = false;
    bool mCommissionerPasscodeReady = false;
    bool mCancelPasscode            = false;
};

/**
 * Represents the Commissioner Delaration message
 * sent by a UDC server to a UDC client.
 */
class DLL_EXPORT CommissionerDeclaration
{
public:
    enum class CdError : uint16_t
    {
        kNoError                                = 0,
        kCommissionableDiscoveryFailed          = 1,
        kPaseConnectionFailed                   = 2,
        kPaseAuthFailed                         = 3,
        kDacValidationFailed                    = 4,
        kAlreadyOnFabric                        = 5,
        kOperationalDiscoveryFailed             = 6,
        kCaseConnectionFailed                   = 7,
        kCaseAuthFailed                         = 8,
        kConfigurationFailed                    = 9,
        kBindingConfigurationFailed             = 10,
        kCommissionerPasscodeNotSupported       = 11,
        kInvalidIdentificationDeclarationParams = 12,
        kAppInstallConsentPending               = 13,
        kAppInstalling                          = 14,
        kAppInstallFailed                       = 15,
        kAppInstalledRetryNeeded                = 16,
        kCommissionerPasscodeDisabled           = 17,
        kUnexpectedCommissionerPasscodeReady    = 18
    };

    constexpr static size_t kUdcTLVDataMaxBytes = 500;

    void SetErrorCode(CdError newValue) { mErrorCode = newValue; };
    CdError GetErrorCode() const { return mErrorCode; };

    void SetNeedsPasscode(bool newValue) { mNeedsPasscode = newValue; };
    bool GetNeedsPasscode() const { return mNeedsPasscode; };

    void SetNoAppsFound(bool newValue) { mNoAppsFound = newValue; };
    bool GetNoAppsFound() const { return mNoAppsFound; };

    void SetPasscodeDialogDisplayed(bool newValue) { mPasscodeDialogDisplayed = newValue; };
    bool GetPasscodeDialogDisplayed() const { return mPasscodeDialogDisplayed; };

    void SetCommissionerPasscode(bool newValue) { mCommissionerPasscode = newValue; };
    bool GetCommissionerPasscode() const { return mCommissionerPasscode; };

    void SetQRCodeDisplayed(bool newValue) { mQRCodeDisplayed = newValue; };
    bool GetQRCodeDisplayed() const { return mQRCodeDisplayed; };

    /**
     *  Writes the CommissionerDeclaration message to the given buffer.
     *
     * @return Total number of bytes written or 0 if an error occurred.
     */
    uint32_t WritePayload(uint8_t * payloadBuffer, size_t payloadBufferSize);

    /**
     *  Reads the CommissionerDeclaration message from the given buffer.
     */
    CHIP_ERROR ReadPayload(uint8_t * payloadBuffer, size_t payloadBufferSize);

    void DebugLog()
    {
        ChipLogDetail(AppServer, "---- Commissioner Declaration Start ----");

        if (mErrorCode != CdError::kNoError)
        {
            ChipLogDetail(AppServer, "\terror code: %d", static_cast<uint16_t>(mErrorCode));
        }

        if (mNeedsPasscode)
        {
            ChipLogDetail(AppServer, "\tneeds passcode: true");
        }
        if (mNoAppsFound)
        {
            ChipLogDetail(AppServer, "\tno apps found: true");
        }
        if (mPasscodeDialogDisplayed)
        {
            ChipLogDetail(AppServer, "\tpasscode dialog displayed: true");
        }
        if (mCommissionerPasscode)
        {
            ChipLogDetail(AppServer, "\tcommissioner passcode: true");
        }
        if (mQRCodeDisplayed)
        {
            ChipLogDetail(AppServer, "\tQR code displayed: true");
        }
        ChipLogDetail(AppServer, "---- Commissioner Declaration End ----");
    }

private:
    // TODO: update spec per the latest tags
    enum CommissionerDeclarationTLVTag
    {
        kErrorCodeTag = 1,
        kNeedsPasscodeTag,
        kNoAppsFoundTag,
        kPasscodeDialogDisplayedTag,
        kCommissionerPasscodeTag,
        kQRCodeDisplayedTag,

        kMaxNum = UINT8_MAX
    };

    CdError mErrorCode            = CdError::kNoError;
    bool mNeedsPasscode           = false;
    bool mNoAppsFound             = false;
    bool mPasscodeDialogDisplayed = false;
    bool mCommissionerPasscode    = false;
    bool mQRCodeDisplayed         = false;
};

class DLL_EXPORT InstanceNameResolver
{
public:
    /**
     * @brief
     *   Called when a UDC message is received specifying the given instanceName
     * This method indicates that UDC Server needs the Commissionable Node corresponding to
     * the given instance name to be found. UDC Server will wait for OnCommissionableNodeFound.
     *
     * @param instanceName DNS-SD instance name for the client requesting commissioning
     *
     */
    virtual void FindCommissionableNode(char * instanceName) = 0;

    virtual ~InstanceNameResolver() = default;
};

class DLL_EXPORT UserConfirmationProvider
{
public:
    /**
     * @brief
     *   Called when an Identification Declaration UDC message has been received
     * and corresponding nodeData has been found.
     * It is expected that the implementer will prompt the user to confirm their intention to
     * commission the given node, and obtain the setup code to allow commissioning to proceed,
     * and then invoke commissioning on the given Node (using CHIP Device Controller, for example)
     *
     *  @param[in]    state           The state for the UDC Client.
     *
     */
    virtual void OnUserDirectedCommissioningRequest(UDCClientState state) = 0;

    /**
     * @brief
     *   Called when an Identification Declaration UDC message has been received
     * with the cancel flag set.
     * It is expected that the implementer will tear down any dialog prompts for the
     * commissionee instance (identified in the UDC client state argument).
     *
     *  @param[in]    state           The state for the UDC Client.
     *
     */
    virtual void OnCancel(UDCClientState state) = 0;

    /**
     * @brief
     *   Called when an Identification Declaration UDC message has been received
     * with the commissioner passcode ready flag set.
     * It is expected that the implementer will invoke commissioning on the
     * commissionee instance (identified in the UDC client state argument).
     *
     *  @param[in]    state           The state for the UDC Client.
     *
     */
    virtual void OnCommissionerPasscodeReady(UDCClientState state) = 0;

    virtual ~UserConfirmationProvider() = default;
};

class DLL_EXPORT CommissionerDeclarationHandler
{
public:
    /**
     * @brief
     *   Called when a Commissioner Declaration UDC message has been received.
     * It is expected that the implementer will de-dup messages received from the
     * same source within a short (1 second) time window.
     *
     *  @param[in]    source       The source of the Commissioner Declaration Message.
     *  @param[in]    cd           The Commissioner Declaration Message.
     *
     */
    virtual void OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source, CommissionerDeclaration cd) = 0;

    virtual ~CommissionerDeclarationHandler() = default;
};

/**
 * TODO:
 * - add processing of Commissioner Declaration flags
 */
class DLL_EXPORT UserDirectedCommissioningClient : public TransportMgrDelegate
{
public:
    /**
     * Send a User Directed Commissioning message to a CHIP node.
     *
     * @param transportMgr  A transport to use for sending the message.
     * @param idMessage     The Identification Declaration message.
     * @param peerAddress   Address of destination.
     *
     * @return CHIP_ERROR_NO_MEMORY if allocation fails.
     *         Other CHIP_ERROR codes as returned by the lower layers.
     *
     */

    CHIP_ERROR SendUDCMessage(TransportMgrBase * transportMgr, IdentificationDeclaration idMessage,
                              chip::Transport::PeerAddress peerAddress);

    /**
     * Encode a User Directed Commissioning message.
     *
     * @param payload       A PacketBufferHandle with the payload.
     *
     * @return CHIP_ERROR_NO_MEMORY if allocation fails.
     *         Other CHIP_ERROR codes as returned by the lower layers.
     *
     */

    CHIP_ERROR EncodeUDCMessage(const System::PacketBufferHandle & payload);

    /**
     * Set the listener to be called when a Commissioner Declaration UDC request is received.
     *
     *  @param[in]    commissionerDeclarationHandler    The callback function to handle the message.
     *
     */
    void SetCommissionerDeclarationHandler(CommissionerDeclarationHandler * commissionerDeclarationHandler)
    {
        mCommissionerDeclarationHandler = commissionerDeclarationHandler;
    }

private:
    void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf) override;

    CommissionerDeclarationHandler * mCommissionerDeclarationHandler = nullptr;
};

/**
 * TODO:
 * - add processing of Identification Declaration flags
 */
class DLL_EXPORT UserDirectedCommissioningServer : public TransportMgrDelegate
{
public:
    /**
     * Set the listener to be called when a UDC request is received
     * and the Instance Name provided needs to be resolved.
     *
     * The resolver should call OnCommissionableNodeFound when the instance is found
     *
     *  @param[in]    instanceNameResolver    The callback function to receive UDC request instance name.
     *
     */
    void SetInstanceNameResolver(InstanceNameResolver * instanceNameResolver) { mInstanceNameResolver = instanceNameResolver; }

    /**
     * Set the listener to be called when a UDC request is received
     * and the Instance Name has been resolved.
     *
     * The provider should prompt the user to allow commissioning of the node and provide the setup code.
     *
     *  @param[in]    userConfirmationProvider    The callback function to obtain user confirmation.
     *
     */
    void SetUserConfirmationProvider(UserConfirmationProvider * userConfirmationProvider)
    {
        mUserConfirmationProvider = userConfirmationProvider;
    }

    /**
     * Update the processing state for a UDC Client based upon instance name.
     *
     * This can be used by the UX to set the state to one of the following values:
     * - kUserDeclined
     * - kObtainingOnboardingPayload
     * - kCommissioningNode
     * - kCommissioningFailed
     *
     *  @param[in]    instanceName    The instance name for the UDC Client.
     *  @param[in]    state           The state for the UDC Client.
     *
     */
    void SetUDCClientProcessingState(char * instanceName, UDCClientProcessingState state);

    /**
     * Reset the processing states for all UDC Clients
     *
     */
    void ResetUDCClientProcessingStates() { mUdcClients.ResetUDCClientStates(); }

    /**
     * Called when a CHIP Node in commissioning mode is found.
     *
     * Lookup instanceName from nodeData in the active UDC Client states
     * and if current state is kDiscoveringNode then change to kPromptingUser and
     * call UX Prompt callback
     *
     *  @param[in]    nodeData        DNS-SD response data.
     *
     */
    void OnCommissionableNodeFound(const Dnssd::DiscoveredNodeData & nodeData);

    /**
     * Get the cache of UDC Clients
     *
     */
    UDCClients<kMaxUDCClients> & GetUDCClients() { return mUdcClients; }

    /**
     * Print the cache of UDC Clients
     *
     */
    void PrintUDCClients();

    /**
     * Send a Commissioner Declaration message to the given peer address
     *
     * Only one message will be sent.
     * Clients should follow spec and send up to 5 times with 100ms sleep between each call.
     */
    CHIP_ERROR SendCDCMessage(CommissionerDeclaration cdMessage, chip::Transport::PeerAddress peerAddress);

    /**
     * Encode a User Directed Commissioning message.
     *
     * @param payload       A PacketBufferHandle with the payload.
     *
     * @return CHIP_ERROR_NO_MEMORY if allocation fails.
     *         Other CHIP_ERROR codes as returned by the lower layers.
     *
     */
    CHIP_ERROR EncodeUDCMessage(const System::PacketBufferHandle & payload);

    /**
     * Assign the transport manager to use for Commissioner Declaration messages
     */
    void SetTransportManager(TransportMgrBase * transportMgr) { mTransportMgr = transportMgr; }

private:
    InstanceNameResolver * mInstanceNameResolver         = nullptr;
    UserConfirmationProvider * mUserConfirmationProvider = nullptr;

    void HandleNewUDC(const Transport::PeerAddress & source, IdentificationDeclaration & id);
    void HandleUDCCancel(IdentificationDeclaration & id);
    void HandleUDCCommissionerPasscodeReady(IdentificationDeclaration & id);
    void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf) override;

    UDCClients<kMaxUDCClients> mUdcClients; // < Active UDC clients

    TransportMgrBase * mTransportMgr = nullptr;
};

} // namespace UserDirectedCommissioning

template <>
struct MessageTypeTraits<UserDirectedCommissioning::MsgType>
{
    static constexpr const Protocols::Id & ProtocolId() { return UserDirectedCommissioning::Id; }

    static auto GetTypeToNameTable()
    {
        static const std::array<MessageTypeNameLookup, 1> typeToNameTable = {
            {
                { UserDirectedCommissioning::MsgType::IdentificationDeclaration, "IdentificationDeclaration" },
            },
        };

        return &typeToNameTable;
    }
};

} // namespace Protocols
} // namespace chip
