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

#include <string>

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.Emplace().SetRaw(mRendezvous.Value());
    }
    else if (!payload.rendezvousInformation.HasValue())
    {
        // Default to not having anything in the discovery capabilities.
        payload.rendezvousInformation.SetValue(RendezvousInformationFlag::kNone);
    }

    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.
    (void) payload.removeSerialNumber();

    auto existingVendorData = payload.getAllOptionalVendorData();
    for (auto & data : existingVendorData)
    {
        (void) 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;
}
