/*
 *   Copyright (c) 2020 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 "SetupPayloadParseCommand.h"
#include <lib/support/StringBuilder.h>
#include <setup_payload/ManualSetupPayloadParser.h>
#include <setup_payload/QRCodeSetupPayloadParser.h>
#include <setup_payload/SetupPayload.h>

#include <string>

using namespace ::chip;

namespace {

#if CHIP_PROGRESS_LOGGING

const char * CustomFlowString(CommissioningFlow flow)
{
    switch (flow)
    {
    case CommissioningFlow::kStandard:
        return "STANDARD";
    case CommissioningFlow::kUserActionRequired:
        return "USER ACTION REQUIRED";
    case CommissioningFlow::kCustom:
        return "CUSTOM";
    }

    return "???";
}

#endif // CHIP_PROGRESS_LOGGING

} // namespace

CHIP_ERROR SetupPayloadParseCommand::Run()
{
    std::string codeString(mCode);
    SetupPayload payload;

    ReturnErrorOnFailure(Parse(codeString, payload));
    ReturnErrorOnFailure(Print(payload));

    return CHIP_NO_ERROR;
}

CHIP_ERROR SetupPayloadParseCommand::Parse(std::string codeString, chip::SetupPayload & payload)
{
    bool isQRCode = IsQRCode(codeString);

    ChipLogDetail(SetupPayload, "Parsing %sRepresentation: %s", isQRCode ? "base38" : "decimal", codeString.c_str());

    return isQRCode ? QRCodeSetupPayloadParser(codeString).populatePayload(payload)
                    : ManualSetupPayloadParser(codeString).populatePayload(payload);
}

CHIP_ERROR SetupPayloadParseCommand::Print(chip::SetupPayload payload)
{
    ChipLogProgress(SetupPayload, "Version:             %u", payload.version);
    ChipLogProgress(SetupPayload, "VendorID:            %u", payload.vendorID);
    ChipLogProgress(SetupPayload, "ProductID:           %u", payload.productID);
    ChipLogProgress(SetupPayload, "Custom flow:         %u    (%s)", to_underlying(payload.commissioningFlow),
                    CustomFlowString(payload.commissioningFlow));
    {
        StringBuilder<128> humanFlags;

        if (!payload.rendezvousInformation.HasValue())
        {
            ChipLogProgress(SetupPayload, "Discovery Bitmask:   UNKNOWN");
        }
        else
        {
            if (payload.rendezvousInformation.Value().HasAny())
            {
                if (payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kSoftAP))
                {
                    humanFlags.Add("Soft-AP");
                }
                if (payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kBLE))
                {
                    if (!humanFlags.Empty())
                    {
                        humanFlags.Add(", ");
                    }
                    humanFlags.Add("BLE");
                }
                if (payload.rendezvousInformation.Value().Has(RendezvousInformationFlag::kOnNetwork))
                {
                    if (!humanFlags.Empty())
                    {
                        humanFlags.Add(", ");
                    }
                    humanFlags.Add("On IP network");
                }
            }
            else
            {
                humanFlags.Add("NONE");
            }

            ChipLogProgress(SetupPayload, "Discovery Bitmask:   0x%02X (%s)", payload.rendezvousInformation.Value().Raw(),
                            humanFlags.c_str());
        }
    }
    if (payload.discriminator.IsShortDiscriminator())
    {
        ChipLogProgress(SetupPayload, "Short discriminator: %u   (0x%x)", payload.discriminator.GetShortValue(),
                        payload.discriminator.GetShortValue());
    }
    else
    {
        ChipLogProgress(SetupPayload, "Long discriminator:  %u   (0x%x)", payload.discriminator.GetLongValue(),
                        payload.discriminator.GetLongValue());
    }
    ChipLogProgress(SetupPayload, "Passcode:            %u", payload.setUpPINCode);

    std::string serialNumber;
    if (payload.getSerialNumber(serialNumber) == CHIP_NO_ERROR)
    {
        ChipLogProgress(SetupPayload, "SerialNumber:        %s", serialNumber.c_str());
    }

    std::vector<OptionalQRCodeInfo> optionalVendorData = payload.getAllOptionalVendorData();
    for (const OptionalQRCodeInfo & info : optionalVendorData)
    {
        bool isTypeString = info.type == optionalQRCodeInfoTypeString;
        bool isTypeInt32  = info.type == optionalQRCodeInfoTypeInt32;
        VerifyOrReturnError(isTypeString || isTypeInt32, CHIP_ERROR_INVALID_ARGUMENT);

        if (isTypeString)
        {
            ChipLogProgress(SetupPayload, "OptionalQRCodeInfo:  tag=%u,string value=%s", info.tag, info.data.c_str());
        }
        else
        {
            ChipLogProgress(SetupPayload, "OptionalQRCodeInfo:  tag=%u,int value=%u", info.tag, info.int32);
        }
    }

    return CHIP_NO_ERROR;
}

bool SetupPayloadParseCommand::IsQRCode(std::string codeString)
{
    return codeString.rfind(kQRCodePrefix) == 0;
}
