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

/**
 *    @file
 *      This file describes a QRCode Setup Payload class to hold
 *      data enumerated from a byte stream
 */

#pragma once

#include <cstdint>
#include <map>
#include <string>
#include <vector>

#include <lib/core/CHIPError.h>
#include <lib/core/Optional.h>
#include <lib/support/BitFlags.h>
#include <lib/support/SetupDiscriminator.h>

namespace chip {

// See section 5.1.2. QR Code in the Matter specification
const int kVersionFieldLengthInBits              = 3;
const int kVendorIDFieldLengthInBits             = 16;
const int kProductIDFieldLengthInBits            = 16;
const int kCommissioningFlowFieldLengthInBits    = 2;
const int kRendezvousInfoFieldLengthInBits       = 8;
const int kPayloadDiscriminatorFieldLengthInBits = SetupDiscriminator::kLongBits;
const int kSetupPINCodeFieldLengthInBits         = 27;
const int kPaddingFieldLengthInBits              = 4;
const int kRawVendorTagLengthInBits              = 7;

// See section 5.1.3. Manual Pairing Code in the Matter specification
const int kManualSetupDiscriminatorFieldLengthInBits  = SetupDiscriminator::kShortBits;
const int kManualSetupChunk1DiscriminatorMsbitsPos    = 0;
const int kManualSetupChunk1DiscriminatorMsbitsLength = 2;
const int kManualSetupChunk1VidPidPresentBitPos =
    (kManualSetupChunk1DiscriminatorMsbitsPos + kManualSetupChunk1DiscriminatorMsbitsLength);
const int kManualSetupChunk2PINCodeLsbitsPos       = 0;
const int kManualSetupChunk2PINCodeLsbitsLength    = 14;
const int kManualSetupChunk2DiscriminatorLsbitsPos = (kManualSetupChunk2PINCodeLsbitsPos + kManualSetupChunk2PINCodeLsbitsLength);
const int kManualSetupChunk2DiscriminatorLsbitsLength = 2;
const int kManualSetupChunk3PINCodeMsbitsPos          = 0;
const int kManualSetupChunk3PINCodeMsbitsLength       = 13;

const int kManualSetupShortCodeCharLength  = 10;
const int kManualSetupLongCodeCharLength   = 20;
const int kManualSetupCodeChunk1CharLength = 1;
const int kManualSetupCodeChunk2CharLength = 5;
const int kManualSetupCodeChunk3CharLength = 4;
const int kManualSetupVendorIdCharLength   = 5;
const int kManualSetupProductIdCharLength  = 5;

// Spec 5.1.4.2 CHIP-Common Reserved Tags
constexpr uint8_t kSerialNumberTag         = 0x00;
constexpr uint8_t kPBKDFIterationsTag      = 0x01;
constexpr uint8_t kBPKFSaltTag             = 0x02;
constexpr uint8_t kNumberOFDevicesTag      = 0x03;
constexpr uint8_t kCommissioningTimeoutTag = 0x04;

constexpr uint32_t kSetupPINCodeMaximumValue   = 99999998;
constexpr uint32_t kSetupPINCodeUndefinedValue = 0;

// clang-format off
const int kTotalPayloadDataSizeInBits =
    kVersionFieldLengthInBits +
    kVendorIDFieldLengthInBits +
    kProductIDFieldLengthInBits +
    kCommissioningFlowFieldLengthInBits +
    kRendezvousInfoFieldLengthInBits +
    kPayloadDiscriminatorFieldLengthInBits +
    kSetupPINCodeFieldLengthInBits +
    kPaddingFieldLengthInBits;
// clang-format on

const int kTotalPayloadDataSizeInBytes = kTotalPayloadDataSizeInBits / 8;

const char * const kQRCodePrefix = "MT:";

/// The rendezvous type this device supports.
enum class RendezvousInformationFlag : uint8_t
{
    kNone      = 0,      ///< Device does not support any method for rendezvous
    kSoftAP    = 1 << 0, ///< Device supports Wi-Fi softAP
    kBLE       = 1 << 1, ///< Device supports BLE
    kOnNetwork = 1 << 2, ///< Device supports Setup on network
};
using RendezvousInformationFlags = chip::BitFlags<RendezvousInformationFlag, uint8_t>;

enum class CommissioningFlow : uint8_t
{
    kStandard = 0,       ///< Device automatically enters pairing mode upon power-up
    kUserActionRequired, ///< Device requires a user interaction to enter pairing mode
    kCustom,             ///< Commissioning steps should be retrieved from the distributed compliance ledger
};

/**
 * A parent struct to hold onboarding payload contents without optional info,
 * for compatibility with devices that don't support std::string or STL.
 */
struct PayloadContents
{
    uint8_t version                     = 0;
    uint16_t vendorID                   = 0;
    uint16_t productID                  = 0;
    CommissioningFlow commissioningFlow = CommissioningFlow::kStandard;
    Optional<RendezvousInformationFlags> rendezvousInformation;
    SetupDiscriminator discriminator;
    uint32_t setUpPINCode = 0;

    bool isValidQRCodePayload() const;
    bool isValidManualCode() const;
    bool operator==(PayloadContents & input) const;

    static bool IsValidSetupPIN(uint32_t setupPIN);

private:
    bool CheckPayloadCommonConstraints() const;
};

enum optionalQRCodeInfoType
{
    optionalQRCodeInfoTypeUnknown,
    optionalQRCodeInfoTypeString,
    optionalQRCodeInfoTypeInt32,
    optionalQRCodeInfoTypeInt64,
    optionalQRCodeInfoTypeUInt32,
    optionalQRCodeInfoTypeUInt64
};

/**
 * A structure to hold optional QR Code info
 */
struct OptionalQRCodeInfo
{
    OptionalQRCodeInfo() { int32 = 0; }

    /*@{*/
    uint8_t tag;                      /**< the tag number of the optional info */
    enum optionalQRCodeInfoType type; /**< the type (String or Int) of the optional info */
    std::string data;                 /**< the string value if type is optionalQRCodeInfoTypeString, otherwise should not be set */
    int32_t int32;                    /**< the integer value if type is optionalQRCodeInfoTypeInt, otherwise should not be set */
    /*@}*/
};

struct OptionalQRCodeInfoExtension : OptionalQRCodeInfo
{
    OptionalQRCodeInfoExtension()
    {
        int32  = 0;
        int64  = 0;
        uint32 = 0;
        uint64 = 0;
    }

    int64_t int64;
    uint64_t uint32;
    uint64_t uint64;
};

class SetupPayload : public PayloadContents
{

    friend class QRCodeSetupPayloadGenerator;
    friend class QRCodeSetupPayloadParser;

public:
    /** @brief A function to add an optional vendor data
     * @param tag tag number in the [0x80-0xFF] range
     * @param data String representation of data to add
     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     **/
    CHIP_ERROR addOptionalVendorData(uint8_t tag, std::string data);

    /** @brief A function to add an optional vendor data
     * @param tag 7 bit [0-127] tag number
     * @param data Integer representation of data to add
     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     **/
    CHIP_ERROR addOptionalVendorData(uint8_t tag, int32_t data);

    /** @brief A function to remove an optional vendor data
     * @param tag 7 bit [0-127] tag number
     * @return Returns a CHIP_ERROR_KEY_NOT_FOUND on error, CHIP_NO_ERROR otherwise
     **/
    CHIP_ERROR removeOptionalVendorData(uint8_t tag);
    /**
     * @brief A function to retrieve the vector of OptionalQRCodeInfo infos
     * @return Returns a vector of optionalQRCodeInfos
     **/
    std::vector<OptionalQRCodeInfo> getAllOptionalVendorData() const;

    /** @brief A function to add a string serial number
     * @param serialNumber string serial number
     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     **/
    CHIP_ERROR addSerialNumber(std::string serialNumber);

    /** @brief A function to add a uint32_t serial number
     * @param serialNumber uint32_t serial number
     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     **/
    CHIP_ERROR addSerialNumber(uint32_t serialNumber);

    /** @brief A function to retrieve serial number as a string
     * @param outSerialNumber retrieved string serial number
     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     **/
    CHIP_ERROR getSerialNumber(std::string & outSerialNumber) const;

    /** @brief A function to remove the serial number from the payload
     * @return Returns a CHIP_ERROR_KEY_NOT_FOUND on error, CHIP_NO_ERROR otherwise
     **/
    CHIP_ERROR removeSerialNumber();

    bool operator==(SetupPayload & input);

private:
    std::map<uint8_t, OptionalQRCodeInfo> optionalVendorData;
    std::map<uint8_t, OptionalQRCodeInfoExtension> optionalExtensionData;

    /** @brief Checks if the tag is CHIP Common type
     * @param tag Tag to be checked
     * @return Returns True if the tag is of Common type
     **/
    static bool IsCommonTag(uint8_t tag);

    /** @brief Checks if the tag is vendor-specific
     * @param tag Tag to be checked
     * @return Returns True if the tag is Vendor-specific
     **/
    static bool IsVendorTag(uint8_t tag);

    /** @brief A function to add an optional QR Code info vendor object
     * @param info Optional QR code info object to add
     * @return Returns a CHIP_ERROR_INVALID_ARGUMENT on error, CHIP_NO_ERROR otherwise
     **/
    CHIP_ERROR addOptionalVendorData(const OptionalQRCodeInfo & info);

    /** @brief A function to add an optional QR Code info CHIP object
     * @param info Optional QR code info object to add
     * @return Returns a CHIP_ERROR_INVALID_ARGUMENT on error, CHIP_NO_ERROR otherwise
     **/
    CHIP_ERROR addOptionalExtensionData(const OptionalQRCodeInfoExtension & info);

    /**
     * @brief A function to retrieve the vector of CHIPQRCodeInfo infos
     * @return Returns a vector of CHIPQRCodeInfos
     **/
    std::vector<OptionalQRCodeInfoExtension> getAllOptionalExtensionData();

    /** @brief A function to retrieve an optional QR Code info vendor object
     * @param tag 7 bit [0-127] tag number
     * @param info retrieved OptionalQRCodeInfo object
     * @return Returns a CHIP_ERROR_KEY_NOT_FOUND on error, CHIP_NO_ERROR otherwise
     **/
    CHIP_ERROR getOptionalVendorData(uint8_t tag, OptionalQRCodeInfo & info);

    /** @brief A function to retrieve an optional QR Code info extended object
     * @param tag 8 bit [128-255] tag number
     * @param info retrieved OptionalQRCodeInfoExtension object
     * @return Returns a CHIP_ERROR_KEY_NOT_FOUND on error, CHIP_NO_ERROR otherwise
     **/
    CHIP_ERROR getOptionalExtensionData(uint8_t tag, OptionalQRCodeInfoExtension & info) const;

    /** @brief A function to retrieve the associated expected numeric value for a tag
     * @param tag 8 bit [0-255] tag number
     * @return Returns an optionalQRCodeInfoType value
     **/
    optionalQRCodeInfoType getNumericTypeFor(uint8_t tag);
};

} // namespace chip
