/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *
 *    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.
 */

#pragma once

#include <bitset>

#include <setup_payload/Base38Decode.h>
#include <setup_payload/Base38Encode.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
#include <setup_payload/QRCodeSetupPayloadParser.h>
#include <setup_payload/SetupPayload.h>

#include <string>

namespace chip {

const uint16_t kSmallBufferSizeInBytes   = 1;
const uint16_t kDefaultBufferSizeInBytes = 512;

const uint8_t kOptionalDefaultStringTag             = 0x82; // Vendor "test" tag
inline constexpr char kOptionalDefaultStringValue[] = "myData";

const uint8_t kOptionalDefaultIntTag    = 0x83; // Vendor "test" tag
const uint32_t kOptionalDefaultIntValue = 12;

inline constexpr char kSerialNumberDefaultStringValue[] = "123456789";
const uint32_t kSerialNumberDefaultUInt32Value          = 123456789;

inline constexpr char kDefaultPayloadQRCode[] = "MT:M5L90MP500K64J00000";

inline SetupPayload GetDefaultPayload()
{
    SetupPayload payload;

    payload.version           = 0;
    payload.vendorID          = 12;
    payload.productID         = 1;
    payload.commissioningFlow = CommissioningFlow::kStandard;
    payload.rendezvousInformation.SetValue(RendezvousInformationFlag::kSoftAP);
    payload.discriminator.SetLongValue(128);
    payload.setUpPINCode = 2048;

    return payload;
}

inline SetupPayload GetDefaultPayloadWithSerialNumber()
{
    SetupPayload payload = GetDefaultPayload();
    payload.addSerialNumber(kSerialNumberDefaultStringValue);

    return payload;
}

inline SetupPayload GetDefaultPayloadWithOptionalDefaults()
{
    SetupPayload payload = GetDefaultPayloadWithSerialNumber();

    payload.addOptionalVendorData(kOptionalDefaultStringTag, kOptionalDefaultStringValue);
    payload.addOptionalVendorData(kOptionalDefaultIntTag, kOptionalDefaultIntValue);

    return payload;
}

inline std::string toBinaryRepresentation(std::string base38Result)
{
    // Remove the kQRCodePrefix
    base38Result.erase(0, strlen(kQRCodePrefix));

    // Decode the base38 encoded string
    std::vector<uint8_t> buffer;
    base38Decode(base38Result, buffer);

    // Convert it to binary
    std::string binaryResult;
    for (size_t i = buffer.size(); i > 0; i--)
    {
        binaryResult += std::bitset<8>(buffer[i - 1]).to_string();
    }

    // Insert spaces after each block
    size_t pos = binaryResult.size();

    pos -= kVersionFieldLengthInBits;
    binaryResult.insert(pos, " ");

    pos -= kVendorIDFieldLengthInBits;
    binaryResult.insert(pos, " ");

    pos -= kProductIDFieldLengthInBits;
    binaryResult.insert(pos, " ");

    pos -= kCommissioningFlowFieldLengthInBits;
    binaryResult.insert(pos, " ");

    pos -= kRendezvousInfoFieldLengthInBits;
    binaryResult.insert(pos, " ");

    pos -= kPayloadDiscriminatorFieldLengthInBits;
    binaryResult.insert(pos, " ");

    pos -= kSetupPINCodeFieldLengthInBits;
    binaryResult.insert(pos, " ");

    pos -= kPaddingFieldLengthInBits;
    binaryResult.insert(pos, " ");

    return binaryResult;
}

inline bool CompareBinary(SetupPayload & payload, std::string & expectedBinary)
{
    QRCodeSetupPayloadGenerator generator(payload);

    std::string result;
    uint8_t optionalInfo[kDefaultBufferSizeInBytes] = {};
    generator.payloadBase38Representation(result, optionalInfo, sizeof(optionalInfo));

    std::string resultBinary = toBinaryRepresentation(result);
    return (expectedBinary == resultBinary);
}

inline bool CheckWriteRead(SetupPayload & inPayload, bool allowInvalidPayload = false)
{
    SetupPayload outPayload;
    std::string result;

    uint8_t optionalInfo[kDefaultBufferSizeInBytes];
    memset(optionalInfo, 0xFF, sizeof(optionalInfo));
    auto generator = QRCodeSetupPayloadGenerator(inPayload);
    generator.SetAllowInvalidPayload(allowInvalidPayload);
    CHIP_ERROR err = generator.payloadBase38Representation(result, optionalInfo, sizeof(optionalInfo));

    if (err != CHIP_NO_ERROR)
    {
        return false;
    }

    outPayload = {};
    QRCodeSetupPayloadParser(result).populatePayload(outPayload);

    return inPayload == outPayload;
}

} // namespace chip
