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

#include "SetupPayloadGenerateCommand.h"
#include <lib/core/CHIPTLV.h>
#include <setup_payload/ManualSetupPayloadGenerator.h>
#include <setup_payload/ManualSetupPayloadParser.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
#include <setup_payload/QRCodeSetupPayloadParser.h>
#include <setup_payload/SetupPayload.h>

using namespace ::chip;

void SetupPayloadGenerateCommand::ConfigurePayload(SetupPayload & payload)
{
    if (mDiscriminator.HasValue())
    {
        payload.discriminator.SetLongValue(mDiscriminator.Value());
    }

    if (mSetUpPINCode.HasValue())
    {
        payload.setUpPINCode = mSetUpPINCode.Value();
    }

    if (mVersion.HasValue())
    {
        payload.version = mVersion.Value();
    }

    if (mVendorId.HasValue())
    {
        payload.vendorID = mVendorId.Value();
    }

    if (mProductId.HasValue())
    {
        payload.productID = mProductId.Value();
    }

    if (mCommissioningMode.HasValue())
    {
        payload.commissioningFlow = static_cast<CommissioningFlow>(mCommissioningMode.Value());
    }
}

CHIP_ERROR SetupPayloadGenerateQRCodeCommand::Run()
{
    SetupPayload payload;

    if (mExistingPayload.HasValue())
    {
        CHIP_ERROR err = QRCodeSetupPayloadParser(mExistingPayload.Value()).populatePayload(payload);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(chipTool, "Invalid existing payload: %" CHIP_ERROR_FORMAT, err.Format());
            return err;
        }
    }

    ConfigurePayload(payload);

    if (mRendezvous.HasValue())
    {
        payload.rendezvousInformation.SetRaw(mRendezvous.Value());
    }

    if (mTLVBytes.HasValue())
    {
        CHIP_ERROR err = PopulatePayloadTLVFromBytes(payload, mTLVBytes.Value());
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(chipTool, "Unable to populate payload TLV: %" CHIP_ERROR_FORMAT, err.Format());
            return err;
        }
    }

    QRCodeSetupPayloadGenerator generator(payload);
    generator.SetAllowInvalidPayload(mAllowInvalidPayload.ValueOr(false));

    std::string code;
    ReturnErrorOnFailure(generator.payloadBase38RepresentationWithAutoTLVBuffer(code));
    // CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE includes various prefixes we don't
    // control (timestamps, process ids, etc).  Let's assume (hope?) that
    // those prefixes use up no more than half the total available space.
    constexpr size_t chunkSize = CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE / 2;
    while (code.size() > chunkSize)
    {
        ChipLogProgress(chipTool, "QR Code: %s", code.substr(0, chunkSize).c_str());
        code = code.substr(chunkSize);
    }
    ChipLogProgress(chipTool, "QR Code: %s", code.c_str());

    return CHIP_NO_ERROR;
}

CHIP_ERROR SetupPayloadGenerateQRCodeCommand::PopulatePayloadTLVFromBytes(SetupPayload & payload, const ByteSpan & tlvBytes)
{
    // First clear out all the existing TVL bits from the payload.  Ignore
    // errors here, because we don't care if those bits are not present.
    payload.removeSerialNumber();

    auto existingVendorData = payload.getAllOptionalVendorData();
    for (auto & data : existingVendorData)
    {
        payload.removeOptionalVendorData(data.tag);
    }

    if (tlvBytes.empty())
    {
        // Used to just clear out the existing TLV.
        return CHIP_NO_ERROR;
    }

    TLV::TLVReader reader;
    reader.Init(tlvBytes);

    // Data is a TLV structure.
    ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));

    TLV::TLVType outerType;
    ReturnErrorOnFailure(reader.EnterContainer(outerType));

    CHIP_ERROR err;
    while ((err = reader.Next()) == CHIP_NO_ERROR)
    {
        TLV::Tag tag = reader.GetTag();
        if (!TLV::IsContextTag(tag))
        {
            ChipLogError(chipTool, "Unexpected non-context TLV tag.");
            return CHIP_ERROR_INVALID_TLV_TAG;
        }

        uint8_t tagNum = static_cast<uint8_t>(TLV::TagNumFromTag(tag));
        if (tagNum < 0x80)
        {
            // Matter-common tag.
            if (tagNum != kSerialNumberTag)
            {
                ChipLogError(chipTool, "No support yet for Matter-common tags other than serial number");
                return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
            }

            // Serial number can be a string or an unsigned integer.
            if (reader.GetType() == TLV::kTLVType_UTF8String)
            {
                CharSpan data;
                ReturnErrorOnFailure(reader.Get(data));
                ReturnErrorOnFailure(payload.addSerialNumber(std::string(data.data(), data.size())));
                continue;
            }

            if (reader.GetType() == TLV::kTLVType_UnsignedInteger)
            {
                uint32_t value;
                ReturnErrorOnFailure(reader.Get(value));
                ReturnErrorOnFailure(payload.addSerialNumber(value));
                continue;
            }

            ChipLogError(chipTool, "Unexpected type for serial number: %d", to_underlying(reader.GetType()));
            return CHIP_ERROR_WRONG_TLV_TYPE;
        }

        // Vendor tag.  We support strings and signed integers.
        if (reader.GetType() == TLV::kTLVType_UTF8String)
        {
            CharSpan data;
            ReturnErrorOnFailure(reader.Get(data));
            ReturnErrorOnFailure(payload.addOptionalVendorData(tagNum, std::string(data.data(), data.size())));
            continue;
        }

        if (reader.GetType() == TLV::kTLVType_SignedInteger)
        {
            int32_t value;
            ReturnErrorOnFailure(reader.Get(value));
            ReturnErrorOnFailure(payload.addOptionalVendorData(tagNum, value));
            continue;
        }

        ChipLogError(chipTool, "Unexpected type for vendor data: %d", to_underlying(reader.GetType()));
        return CHIP_ERROR_WRONG_TLV_TYPE;
    }

    VerifyOrReturnError(err == CHIP_END_OF_TLV, err);

    ReturnErrorOnFailure(reader.ExitContainer(outerType));
    ReturnErrorOnFailure(reader.VerifyEndOfContainer());

    return CHIP_NO_ERROR;
}

CHIP_ERROR SetupPayloadGenerateManualCodeCommand::Run()
{
    SetupPayload payload;

    if (mExistingPayload.HasValue())
    {
        CHIP_ERROR err = ManualSetupPayloadParser(mExistingPayload.Value()).populatePayload(payload);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(chipTool, "Invalid existing payload: %" CHIP_ERROR_FORMAT, err.Format());
            return err;
        }
    }

    ConfigurePayload(payload);

    ManualSetupPayloadGenerator generator(payload);
    generator.SetAllowInvalidPayload(mAllowInvalidPayload.ValueOr(false));
    generator.SetForceShortCode(mForceShortCode.ValueOr(false));

    std::string code;
    ReturnErrorOnFailure(generator.payloadDecimalStringRepresentation(code));
    ChipLogProgress(chipTool, "Manual Code: %s", code.c_str());

    return CHIP_NO_ERROR;
}
