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

/**
 *    @file
 *      This file implements an object for a Matter User Directed Commissioning unsolicited
 *      recipient (server).
 *
 */

#include "UserDirectedCommissioning.h"
#include <lib/core/CHIPSafeCasts.h>
#include <system/TLVPacketBufferBackingStore.h>
#include <transport/raw/Base.h>

#include <unistd.h>

namespace chip {
namespace Protocols {
namespace UserDirectedCommissioning {

void UserDirectedCommissioningServer::OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msg,
                                                        Transport::MessageTransportContext * ctxt)
{
    char addrBuffer[chip::Transport::PeerAddress::kMaxToStringSize];
    source.ToString(addrBuffer);
    ChipLogProgress(AppServer, "UserDirectedCommissioningServer::OnMessageReceived from %s", addrBuffer);

    PacketHeader packetHeader;

    ReturnOnFailure(packetHeader.DecodeAndConsume(msg));

    if (packetHeader.IsEncrypted())
    {
        ChipLogError(AppServer, "UDC encryption flag set - ignoring");
        return;
    }

    PayloadHeader payloadHeader;
    ReturnOnFailure(payloadHeader.DecodeAndConsume(msg));

    ChipLogProgress(AppServer, "IdentityDeclaration DataLength()=%" PRIu32, static_cast<uint32_t>(msg->DataLength()));

    uint8_t udcPayload[IdentificationDeclaration::kUdcTLVDataMaxBytes];
    size_t udcPayloadLength = std::min<size_t>(msg->DataLength(), sizeof(udcPayload));
    msg->Read(udcPayload, udcPayloadLength);

    IdentificationDeclaration id;
    id.ReadPayload(udcPayload, sizeof(udcPayload));

    if (id.GetCancelPasscode())
    {
        HandleUDCCancel(id);
        return;
    }

    if (id.GetCommissionerPasscodeReady())
    {
        HandleUDCCommissionerPasscodeReady(id);
        return;
    }

    HandleNewUDC(source, id);
}

void UserDirectedCommissioningServer::HandleNewUDC(const Transport::PeerAddress & source, IdentificationDeclaration & id)
{
    char * instanceName = (char *) id.GetInstanceName();
    ChipLogProgress(AppServer, "HandleNewUDC instance=%s ", id.GetInstanceName());

    UDCClientState * client = mUdcClients.FindUDCClientState(instanceName);
    if (client == nullptr)
    {
        ChipLogProgress(AppServer, "UDC new instance state received");

        id.DebugLog();

        CHIP_ERROR err;
        err = mUdcClients.CreateNewUDCClientState(instanceName, &client);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(AppServer, "UDC error creating new connection state");
            return;
        }

        if (id.HasDiscoveryInfo())
        {
            // if we received mDNS info, skip the commissionable lookup
            ChipLogDetail(AppServer, "UDC discovery info provided");
            mUdcClients.MarkUDCClientActive(client);

            client->SetUDCClientProcessingState(UDCClientProcessingState::kPromptingUser);
            client->SetPeerAddress(source);

            id.UpdateClientState(client);

            // Call the registered mUserConfirmationProvider, if any.
            if (mUserConfirmationProvider != nullptr)
            {
                mUserConfirmationProvider->OnUserDirectedCommissioningRequest(*client);
            }
            return;
        }

        // Call the registered InstanceNameResolver, if any.
        if (mInstanceNameResolver != nullptr)
        {
            mInstanceNameResolver->FindCommissionableNode(instanceName);
        }
        else
        {
            ChipLogError(AppServer, "UserDirectedCommissioningServer::OnMessageReceived no mInstanceNameResolver registered");
        }
    }
    mUdcClients.MarkUDCClientActive(client);
}

void UserDirectedCommissioningServer::HandleUDCCancel(IdentificationDeclaration & id)
{
    char * instanceName = (char *) id.GetInstanceName();
    ChipLogProgress(AppServer, "HandleUDCCancel instance=%s ", id.GetInstanceName());

    UDCClientState * client = mUdcClients.FindUDCClientState(instanceName);
    if (client == nullptr)
    {
        ChipLogProgress(AppServer, "UDC no matching instance found");
        return;
    }
    id.DebugLog();
    mUdcClients.MarkUDCClientActive(client);

    // Call the registered mUserConfirmationProvider, if any.
    if (mUserConfirmationProvider != nullptr)
    {
        mUserConfirmationProvider->OnCancel(*client);
    }

    // reset this entry so that the client can try again without waiting an hour
    client->Reset();
}

void UserDirectedCommissioningServer::HandleUDCCommissionerPasscodeReady(IdentificationDeclaration & id)
{
    char * instanceName = (char *) id.GetInstanceName();
    ChipLogProgress(AppServer, "HandleUDCCommissionerPasscodeReady instance=%s ", id.GetInstanceName());

    UDCClientState * client = mUdcClients.FindUDCClientState(instanceName);
    if (client == nullptr)
    {
        ChipLogProgress(AppServer, "UDC no matching instance found");
        return;
    }
    if (client->GetUDCClientProcessingState() != UDCClientProcessingState::kWaitingForCommissionerPasscodeReady)
    {
        ChipLogProgress(AppServer, "UDC instance not in waiting for passcode ready state");
        return;
    }
    id.DebugLog();
    mUdcClients.MarkUDCClientActive(client);
    client->SetUDCClientProcessingState(UDCClientProcessingState::kObtainingOnboardingPayload);

    // Call the registered mUserConfirmationProvider, if any.
    if (mUserConfirmationProvider != nullptr)
    {
        mUserConfirmationProvider->OnCommissionerPasscodeReady(*client);
    }
}

CHIP_ERROR UserDirectedCommissioningServer::SendCDCMessage(CommissionerDeclaration cd, chip::Transport::PeerAddress peerAddress)
{
    if (mTransportMgr == nullptr)
    {
        ChipLogError(AppServer, "CDC: No transport manager\n");
        return CHIP_ERROR_INCORRECT_STATE;
    }
    uint8_t idBuffer[IdentificationDeclaration::kUdcTLVDataMaxBytes];
    uint32_t length = cd.WritePayload(idBuffer, sizeof(idBuffer));
    if (length == 0)
    {
        ChipLogError(AppServer, "CDC: error writing payload\n");
        return CHIP_ERROR_INTERNAL;
    }

    chip::System::PacketBufferHandle payload = chip::MessagePacketBuffer::NewWithData(idBuffer, length);
    if (payload.IsNull())
    {
        ChipLogError(AppServer, "Unable to allocate packet buffer\n");
        return CHIP_ERROR_NO_MEMORY;
    }
    ReturnErrorOnFailure(EncodeUDCMessage(payload));

    cd.DebugLog();
    ChipLogProgress(Inet, "Sending CDC msg");

    auto err = mTransportMgr->SendMessage(peerAddress, std::move(payload));
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(AppServer, "CDC SendMessage failed: %" CHIP_ERROR_FORMAT, err.Format());
        return err;
    }

    ChipLogProgress(Inet, "CDC msg sent");
    return CHIP_NO_ERROR;
}

CHIP_ERROR UserDirectedCommissioningServer::EncodeUDCMessage(const System::PacketBufferHandle & payload)
{
    PayloadHeader payloadHeader;
    PacketHeader packetHeader;

    payloadHeader.SetMessageType(MsgType::IdentificationDeclaration).SetInitiator(true).SetNeedsAck(false);

    VerifyOrReturnError(!payload.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(!payload->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
    VerifyOrReturnError(payload->TotalLength() <= kMaxAppMessageLen, CHIP_ERROR_MESSAGE_TOO_LONG);

    ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(payload));

    ReturnErrorOnFailure(packetHeader.EncodeBeforeData(payload));

    return CHIP_NO_ERROR;
}

CHIP_ERROR IdentificationDeclaration::ReadPayload(uint8_t * udcPayload, size_t payloadBufferSize)
{
    size_t i = 0;
    while (i < std::min<size_t>(sizeof(mInstanceName), payloadBufferSize) && udcPayload[i] != '\0')
    {
        mInstanceName[i] = (char) udcPayload[i];
        i++;
    }
    mInstanceName[i] = '\0';

    if (payloadBufferSize <= sizeof(mInstanceName))
    {
        ChipLogProgress(AppServer, "UDC - No TLV information in Identification Declaration");
        return CHIP_NO_ERROR;
    }
    // advance i to the end of the fixed length block containing instance name
    i = sizeof(mInstanceName);

    CHIP_ERROR err;

    TLV::TLVReader reader;
    reader.Init(udcPayload + i, payloadBufferSize - i);

    // read the envelope
    ReturnErrorOnFailure(reader.Next(chip::TLV::kTLVType_Structure, chip::TLV::AnonymousTag()));

    chip::TLV::TLVType outerContainerType = chip::TLV::kTLVType_Structure;
    ReturnErrorOnFailure(reader.EnterContainer(outerContainerType));

    while ((err = reader.Next()) == CHIP_NO_ERROR)
    {
        chip::TLV::Tag containerTag = reader.GetTag();
        if (!TLV::IsContextTag(containerTag))
        {
            ChipLogError(AppServer, "Unexpected non-context TLV tag.");
            return CHIP_ERROR_INVALID_TLV_TAG;
        }
        uint8_t tagNum = static_cast<uint8_t>(chip::TLV::TagNumFromTag(containerTag));

        switch (tagNum)
        {
        case kVendorIdTag:
            // vendorId
            err = reader.Get(mVendorId);
            break;
        case kProductIdTag:
            // productId
            err = reader.Get(mProductId);
            break;
        case kCdPortTag:
            // port
            err = reader.Get(mCdPort);
            break;
        case kDeviceNameTag:
            // deviceName
            err = reader.GetString(mDeviceName, sizeof(mDeviceName));
            break;
        case kPairingInstTag:
            // pairingInst
            err = reader.GetString(mPairingInst, sizeof(mPairingInst));
            break;
        case kPairingHintTag:
            // pairingHint
            err = reader.Get(mPairingHint);
            break;
        case kRotatingIdTag:
            // rotatingId
            mRotatingIdLen = reader.GetLength();
            err            = reader.GetBytes(mRotatingId, sizeof(mRotatingId));
            break;
        case kTargetAppListTag:
            // app vendor list
            {
                ChipLogProgress(AppServer, "TLV found an applist");
                chip::TLV::TLVType listContainerType = chip::TLV::kTLVType_List;
                ReturnErrorOnFailure(reader.EnterContainer(listContainerType));

                while ((err = reader.Next()) == CHIP_NO_ERROR && mNumTargetAppInfos < sizeof(mTargetAppInfos))
                {
                    containerTag = reader.GetTag();
                    if (!TLV::IsContextTag(containerTag))
                    {
                        ChipLogError(AppServer, "Unexpected non-context TLV tag.");
                        return CHIP_ERROR_INVALID_TLV_TAG;
                    }
                    tagNum = static_cast<uint8_t>(chip::TLV::TagNumFromTag(containerTag));
                    if (tagNum == kTargetAppTag)
                    {
                        ReturnErrorOnFailure(reader.EnterContainer(outerContainerType));
                        uint16_t appVendorId  = 0;
                        uint16_t appProductId = 0;

                        while ((err = reader.Next()) == CHIP_NO_ERROR)
                        {
                            containerTag = reader.GetTag();
                            if (!TLV::IsContextTag(containerTag))
                            {
                                ChipLogError(AppServer, "Unexpected non-context TLV tag.");
                                return CHIP_ERROR_INVALID_TLV_TAG;
                            }
                            tagNum = static_cast<uint8_t>(chip::TLV::TagNumFromTag(containerTag));
                            if (tagNum == kAppVendorIdTag)
                            {
                                err = reader.Get(appVendorId);
                            }
                            else if (tagNum == kAppProductIdTag)
                            {
                                err = reader.Get(appProductId);
                            }
                        }
                        if (err == CHIP_END_OF_TLV)
                        {
                            ChipLogProgress(AppServer, "TLV end of struct TLV");
                            ReturnErrorOnFailure(reader.ExitContainer(outerContainerType));
                        }
                        if (appVendorId != 0)
                        {
                            mTargetAppInfos[mNumTargetAppInfos].vendorId  = appVendorId;
                            mTargetAppInfos[mNumTargetAppInfos].productId = appProductId;
                            mNumTargetAppInfos++;
                        }
                    }
                    else
                    {
                        ChipLogError(AppServer, "unrecognized tag %d", tagNum);
                    }
                }
                if (err == CHIP_END_OF_TLV)
                {
                    ChipLogProgress(AppServer, "TLV end of array");
                    ReturnErrorOnFailure(reader.ExitContainer(listContainerType));
                }
            }
            break;
        case kNoPasscodeTag:
            err = reader.Get(mNoPasscode);
            break;
        case kCdUponPasscodeDialogTag:
            err = reader.Get(mCdUponPasscodeDialog);
            break;
        case kCommissionerPasscodeTag:
            err = reader.Get(mCommissionerPasscode);
            break;
        case kCommissionerPasscodeReadyTag:
            err = reader.Get(mCommissionerPasscodeReady);
            break;
        case kCancelPasscodeTag:
            err = reader.Get(mCancelPasscode);
            break;
        }
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(AppServer, "IdentificationDeclaration::ReadPayload read error %" CHIP_ERROR_FORMAT, err.Format());
        }
    }

    if (err == CHIP_END_OF_TLV)
    {
        // Exiting container
        ReturnErrorOnFailure(reader.ExitContainer(outerContainerType));
    }
    else
    {
        ChipLogError(AppServer, "IdentificationDeclaration::ReadPayload exiting early error %" CHIP_ERROR_FORMAT, err.Format());
    }

    ChipLogProgress(AppServer, "UDC TLV parse complete");
    return CHIP_NO_ERROR;
}

/**
 *  Reset the connection state to a completely uninitialized status.
 */
uint32_t CommissionerDeclaration::WritePayload(uint8_t * payloadBuffer, size_t payloadBufferSize)
{
    CHIP_ERROR err;

    chip::TLV::TLVWriter writer;

    writer.Init(payloadBuffer, payloadBufferSize);

    chip::TLV::TLVType outerContainerType = chip::TLV::kTLVType_Structure;
    VerifyOrExit(CHIP_NO_ERROR ==
                     (err = writer.StartContainer(chip::TLV::AnonymousTag(), chip::TLV::kTLVType_Structure, outerContainerType)),
                 LogErrorOnFailure(err));

    VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kErrorCodeTag), GetErrorCode())), LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kNeedsPasscodeTag), mNeedsPasscode)),
                 LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kNoAppsFoundTag), mNoAppsFound)),
                 LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR ==
                     (err = writer.PutBoolean(chip::TLV::ContextTag(kPasscodeDialogDisplayedTag), mPasscodeDialogDisplayed)),
                 LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kCommissionerPasscodeTag), mCommissionerPasscode)),
                 LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kQRCodeDisplayedTag), mQRCodeDisplayed)),
                 LogErrorOnFailure(err));

    VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(outerContainerType)), LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.Finalize()), LogErrorOnFailure(err));

    ChipLogProgress(AppServer, "TLV write done");

    return writer.GetLengthWritten();

exit:
    return 0;
}

void UserDirectedCommissioningServer::SetUDCClientProcessingState(char * instanceName, UDCClientProcessingState state)
{
    UDCClientState * client = mUdcClients.FindUDCClientState(instanceName);
    if (client == nullptr)
    {
        CHIP_ERROR err;
        err = mUdcClients.CreateNewUDCClientState(instanceName, &client);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(AppServer,
                         "UserDirectedCommissioningServer::SetUDCClientProcessingState error creating new connection state");
            return;
        }
    }

    ChipLogDetail(AppServer, "SetUDCClientProcessingState instance=%s new state=%d", StringOrNullMarker(instanceName), (int) state);

    client->SetUDCClientProcessingState(state);

    mUdcClients.MarkUDCClientActive(client);
}

void UserDirectedCommissioningServer::OnCommissionableNodeFound(const Dnssd::DiscoveredNodeData & discNodeData)
{
    if (!discNodeData.Is<Dnssd::CommissionNodeData>())
    {
        return;
    }

    const Dnssd::CommissionNodeData & nodeData = discNodeData.Get<Dnssd::CommissionNodeData>();
    if (nodeData.numIPs == 0)
    {
        ChipLogError(AppServer, "OnCommissionableNodeFound no IP addresses returned for instance name=%s", nodeData.instanceName);
        return;
    }
    if (nodeData.port == 0)
    {
        ChipLogError(AppServer, "OnCommissionableNodeFound no port returned for instance name=%s", nodeData.instanceName);
        return;
    }

    UDCClientState * client = mUdcClients.FindUDCClientState(nodeData.instanceName);
    if (client != nullptr && client->GetUDCClientProcessingState() == UDCClientProcessingState::kDiscoveringNode)
    {
        ChipLogDetail(AppServer, "OnCommissionableNodeFound instance: name=%s old_state=%d new_state=%d", client->GetInstanceName(),
                      (int) client->GetUDCClientProcessingState(), (int) UDCClientProcessingState::kPromptingUser);
        client->SetUDCClientProcessingState(UDCClientProcessingState::kPromptingUser);

#if INET_CONFIG_ENABLE_IPV4
        // prefer IPv4 if its an option
        bool foundV4 = false;
        for (unsigned i = 0; i < nodeData.numIPs; ++i)
        {
            if (nodeData.ipAddress[i].IsIPv4())
            {
                foundV4 = true;
                client->SetPeerAddress(chip::Transport::PeerAddress::UDP(nodeData.ipAddress[i], nodeData.port));
                break;
            }
        }
        // use IPv6 as last resort
        if (!foundV4)
        {
            client->SetPeerAddress(chip::Transport::PeerAddress::UDP(nodeData.ipAddress[0], nodeData.port));
        }
#else  // INET_CONFIG_ENABLE_IPV4
       // if we only support V6, then try to find a v6 address
        bool foundV6 = false;
        for (unsigned i = 0; i < nodeData.numIPs; ++i)
        {
            if (nodeData.ipAddress[i].IsIPv6())
            {
                foundV6 = true;
                client->SetPeerAddress(chip::Transport::PeerAddress::UDP(nodeData.ipAddress[i], nodeData.port));
                break;
            }
        }
        // last resort, try with what we have
        if (!foundV6)
        {
            ChipLogError(AppServer, "OnCommissionableNodeFound no v6 returned for instance name=%s", nodeData.instanceName);
            client->SetPeerAddress(chip::Transport::PeerAddress::UDP(nodeData.ipAddress[0], nodeData.port));
        }
#endif // INET_CONFIG_ENABLE_IPV4

        client->SetDeviceName(nodeData.deviceName);
        client->SetLongDiscriminator(nodeData.longDiscriminator);
        client->SetVendorId(nodeData.vendorId);
        client->SetProductId(nodeData.productId);
        client->SetRotatingId(nodeData.rotatingId, nodeData.rotatingIdLen);

        // Call the registered mUserConfirmationProvider, if any.
        if (mUserConfirmationProvider != nullptr)
        {
            mUserConfirmationProvider->OnUserDirectedCommissioningRequest(*client);
        }
    }
}

void UserDirectedCommissioningServer::PrintUDCClients()
{
    for (uint8_t i = 0; i < kMaxUDCClients; i++)
    {
        UDCClientState * state = GetUDCClients().GetUDCClientState(i);
        if (state == nullptr)
        {
            ChipLogProgress(AppServer, "UDC Client[%d] null", i);
        }
        else
        {
            char addrBuffer[chip::Transport::PeerAddress::kMaxToStringSize];
            state->GetPeerAddress().ToString(addrBuffer);

            char rotatingIdString[chip::Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
            Encoding::BytesToUppercaseHexString(state->GetRotatingId(), chip::Dnssd::kMaxRotatingIdLen, rotatingIdString,
                                                sizeof(rotatingIdString));

            ChipLogProgress(AppServer, "UDC Client[%d] instance=%s deviceName=%s address=%s, vid/pid=%d/%d disc=%d rid=%s", i,
                            state->GetInstanceName(), state->GetDeviceName(), addrBuffer, state->GetVendorId(),
                            state->GetProductId(), state->GetLongDiscriminator(), rotatingIdString);
        }
    }
}

} // namespace UserDirectedCommissioning
} // namespace Protocols
} // namespace chip
