/*
 *
 *    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 implements an object for a Matter User Directed Commissioning unsolicited
 *      initiator (client).
 *
 */

#include "UserDirectedCommissioning.h"
#include <transport/raw/Base.h>

#ifdef __ZEPHYR__
#include <zephyr/kernel.h>
#endif // __ZEPHYR__

#include <unistd.h>

namespace chip {
namespace Protocols {
namespace UserDirectedCommissioning {

CHIP_ERROR UserDirectedCommissioningClient::SendUDCMessage(TransportMgrBase * transportMgr, IdentificationDeclaration id,
                                                           chip::Transport::PeerAddress peerAddress)
{
    uint8_t idBuffer[IdentificationDeclaration::kUdcTLVDataMaxBytes];
    uint32_t length = id.WritePayload(idBuffer, sizeof(idBuffer));
    if (length == 0)
    {
        ChipLogError(AppServer, "UDC: 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));

    id.DebugLog();
    ChipLogProgress(Inet, "Sending UDC msg");

    // send UDC message 5 times per spec (no ACK on this message)
    for (unsigned int i = 0; i < 5; i++)
    {
        auto msgCopy = payload.CloneData();
        VerifyOrReturnError(!msgCopy.IsNull(), CHIP_ERROR_NO_MEMORY);

        auto err = transportMgr->SendMessage(peerAddress, std::move(msgCopy));
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(AppServer, "UDC SendMessage failed: %" CHIP_ERROR_FORMAT, err.Format());
            return err;
        }
        // Zephyr doesn't provide usleep implementation.
#ifdef __ZEPHYR__
        k_usleep(100 * 1000); // 100ms
#else
        usleep(100 * 1000); // 100ms
#endif // __ZEPHYR__
    }

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

CHIP_ERROR UserDirectedCommissioningClient::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;
}

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

    chip::TLV::TLVWriter writer;
    chip::TLV::TLVType listContainerType = chip::TLV::kTLVType_List;

    memcpy(payloadBuffer, mInstanceName, sizeof(mInstanceName));

    writer.Init(payloadBuffer + sizeof(mInstanceName), payloadBufferSize - sizeof(mInstanceName));

    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(kVendorIdTag), GetVendorId())), LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kProductIdTag), GetProductId())), LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutString(chip::TLV::ContextTag(kDeviceNameTag), mDeviceName)),
                 LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutString(chip::TLV::ContextTag(kPairingInstTag), mPairingInst)),
                 LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kPairingHintTag), mPairingHint)), LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kCdPortTag), GetCdPort())), LogErrorOnFailure(err));

    VerifyOrExit(
        CHIP_NO_ERROR ==
            (err = writer.PutBytes(chip::TLV::ContextTag(kRotatingIdTag), mRotatingId, static_cast<uint8_t>(mRotatingIdLen))),
        LogErrorOnFailure(err));

    if (mNumTargetAppInfos > 0)
    {
        // AppVendorIdList
        VerifyOrExit(CHIP_NO_ERROR ==
                         (err = writer.StartContainer(chip::TLV::ContextTag(kTargetAppListTag), chip::TLV::kTLVType_List,
                                                      listContainerType)),
                     LogErrorOnFailure(err));
        for (size_t i = 0; i < mNumTargetAppInfos; i++)
        {
            // start the TargetApp structure
            VerifyOrExit(CHIP_NO_ERROR ==
                             (err = writer.StartContainer(chip::TLV::ContextTag(kTargetAppTag), chip::TLV::kTLVType_Structure,
                                                          outerContainerType)),
                         LogErrorOnFailure(err));
            // add the vendor Id
            VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kAppVendorIdTag), mTargetAppInfos[i].vendorId)),
                         LogErrorOnFailure(err));
            VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kAppProductIdTag), mTargetAppInfos[i].productId)),
                         LogErrorOnFailure(err));
            // end the TargetApp structure
            VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(outerContainerType)), LogErrorOnFailure(err));
        }
        VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(listContainerType)), LogErrorOnFailure(err));
    }

    VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kNoPasscodeTag), mNoPasscode)),
                 LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kCdUponPasscodeDialogTag), mCdUponPasscodeDialog)),
                 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(kCommissionerPasscodeReadyTag), mCommissionerPasscodeReady)),
                 LogErrorOnFailure(err));
    VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kCancelPasscodeTag), mCancelPasscode)),
                 LogErrorOnFailure(err));

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

    return writer.GetLengthWritten() + static_cast<uint32_t>(sizeof(mInstanceName));

exit:
    ChipLogError(AppServer, "IdentificationDeclaration::WritePayload exiting early error %" CHIP_ERROR_FORMAT, err.Format());
    return 0;
}

CHIP_ERROR CommissionerDeclaration::ReadPayload(uint8_t * udcPayload, size_t payloadBufferSize)
{
    CHIP_ERROR err;

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

    // 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 kErrorCodeTag:
            err = reader.Get(mErrorCode);
            break;
        case kNeedsPasscodeTag:
            err = reader.Get(mNeedsPasscode);
            break;
        case kNoAppsFoundTag:
            err = reader.Get(mNoAppsFound);
            break;
        case kPasscodeDialogDisplayedTag:
            err = reader.Get(mPasscodeDialogDisplayed);
            break;
        case kCommissionerPasscodeTag:
            err = reader.Get(mCommissionerPasscode);
            break;
        case kQRCodeDisplayedTag:
            err = reader.Get(mQRCodeDisplayed);
            break;
        }
    }

    if (err == CHIP_END_OF_TLV)
    {
        // Exiting container
        ReturnErrorOnFailure(reader.ExitContainer(outerContainerType));
    }

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

void UserDirectedCommissioningClient::OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msg,
                                                        Transport::MessageTransportContext * ctxt)
{
    char addrBuffer[chip::Transport::PeerAddress::kMaxToStringSize];
    source.ToString(addrBuffer);

    ChipLogProgress(AppServer, "UserDirectedCommissioningClient::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, "CommissionerDeclaration 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);

    CommissionerDeclaration cd;
    cd.ReadPayload(udcPayload, sizeof(udcPayload));
    cd.DebugLog();

    // Call the registered mCommissionerDeclarationHandler, if any.
    if (mCommissionerDeclarationHandler != nullptr)
    {
        mCommissionerDeclarationHandler->OnCommissionerDeclarationMessage(source, cd);
    }
}

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