/*
 *
 *    Copyright (c) 2021 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 <lib/core/CHIPError.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/Span.h>

#include <cstdint>

namespace chip {
namespace Credentials {

struct VendorReservedElement
{
    uint16_t vendorId;
    uint16_t profileNum;
    uint32_t tagNum;
    ByteSpan vendorReservedData;
};

// extract elements out of the device attestation bytespan
class DeviceAttestationVendorReservedDeconstructor
{

public:
    DeviceAttestationVendorReservedDeconstructor() {}

    // Read TLV until first profile tag
    CHIP_ERROR PrepareToReadVendorReservedElements(const ByteSpan & attestationElements, size_t count)
    {
        mIsInitialized         = false;
        mIsDone                = false;
        mNumVendorReservedData = count;
        mAttestationData       = attestationElements;

        mTlvReader.Init(mAttestationData);
        ReturnErrorOnFailure(mTlvReader.Next(containerType, TLV::AnonymousTag()));
        ReturnErrorOnFailure(mTlvReader.EnterContainer(containerType));

        // position to first ProfileTag
        while (true)
        {
            CHIP_ERROR err = mTlvReader.Next();
            if (err == CHIP_END_OF_TLV)
            {
                mIsDone = true;
                break;
            }

            ReturnErrorOnFailure(err);

            TLV::Tag tag = mTlvReader.GetTag();
            if (!TLV::IsContextTag(tag))
                break;
        }
        // positioned to first non-context tag (vendor reserved data)
        mIsInitialized  = true;
        mIsAtFirstToken = true;
        return CHIP_NO_ERROR;
    }

    size_t GetNumberOfElements() const { return mNumVendorReservedData; }

    /**
     *  @brief Return next VendorReserved element. PrepareToReadVendorReservedElements must be called first.
     *
     *  @param[out] element  Next vendor Reserved element
     *
     *  @returns   CHIP_NO_ERROR on success
     *             CHIP_ERROR_INCORRECT_STATE if PrepareToReadVendorReservedElements hasn't been called first
     *             CHIP_ERROR_UNEXPECTED_TLV_ELEMENT if we reach non-profile-specific tags or vendorId is zero
     *             CHIP_END_OF_TLV if not further entries are present
     */
    CHIP_ERROR GetNextVendorReservedElement(struct VendorReservedElement & element)
    {
        VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
        if (mIsDone)
        {
            return CHIP_END_OF_TLV;
        }

        if (mIsAtFirstToken)
        {
            // Already had a Next() done for us by PrepareToReadVendorReservedElements
            // so we don't Next() since we should be pointing at a vendor-reserved.
            mIsAtFirstToken = false;
        }
        else
        {
            CHIP_ERROR error = mTlvReader.Next();
            if (error == CHIP_END_OF_TLV)
            {
                mIsDone = true;
            }
            ReturnErrorOnFailure(error);
        }

        TLV::Tag tag = mTlvReader.GetTag();
        if (!TLV::IsProfileTag(tag))
        {
            return CHIP_ERROR_UNEXPECTED_TLV_ELEMENT;
        }

        // tag is profile tag
        element.vendorId   = TLV::VendorIdFromTag(tag);
        element.profileNum = TLV::ProfileNumFromTag(tag);
        element.tagNum     = TLV::TagNumFromTag(tag);

        ReturnErrorOnFailure(mTlvReader.GetByteView(element.vendorReservedData));

        return CHIP_NO_ERROR;
    }

private:
    size_t mNumVendorReservedData; // number of VendorReserved entries (could be 0)
    ByteSpan mAttestationData;
    bool mIsInitialized  = false;
    bool mIsAtFirstToken = false;
    bool mIsDone         = false;
    TLV::ContiguousBufferTLVReader mTlvReader;
    TLV::TLVType containerType = TLV::kTLVType_Structure;
};

class DeviceAttestationVendorReservedConstructor
{
public:
    DeviceAttestationVendorReservedConstructor(struct VendorReservedElement * array, size_t size) : mElements(array), mMaxSize(size)
    {}

    typedef const struct VendorReservedElement * const_iterator;

    const_iterator Next()
    {
        VerifyOrReturnError(mCurrentIndex < mNumEntriesUsed, nullptr);
        return &mElements[mCurrentIndex++];
    }

    const_iterator cbegin()
    {
        // sort the array in place and return the head element.
        do_sorting();
        mCurrentIndex = 0;
        return mElements;
    }

    CHIP_ERROR addVendorReservedElement(uint16_t vendorId, uint16_t profileNum, uint32_t tagNum, ByteSpan span)
    {
        if (mNumEntriesUsed == mMaxSize)
            return CHIP_ERROR_NO_MEMORY;

        mElements[mNumEntriesUsed].tagNum             = tagNum;
        mElements[mNumEntriesUsed].profileNum         = profileNum;
        mElements[mNumEntriesUsed].vendorId           = vendorId;
        mElements[mNumEntriesUsed].vendorReservedData = span;
        mNumEntriesUsed++;
        return CHIP_NO_ERROR;
    }

    size_t GetNumberOfElements() const { return mNumEntriesUsed; }

private:
    /*
     * Sort according to A.2.4 in the spec.
     * Mark all sorted entries by setting used flag.
     * Order is head to tail, sorted by next
     * Executed when entries are about to be read
     */
    void do_sorting()
    {
        size_t starting = 0;

        while (starting < mNumEntriesUsed)
        {
            uint32_t minVendor = UINT32_MAX;

            // find lowest vendorId
            size_t i;
            for (i = starting; i < mNumEntriesUsed; i++)
            {
                if (mElements[i].vendorId < minVendor)
                {
                    minVendor = mElements[i].vendorId;
                }
            }

            uint32_t minProfile = UINT32_MAX;
            // find lowest ProfileNum
            for (i = starting; i < mNumEntriesUsed; i++)
            {
                if (mElements[i].vendorId == minVendor)
                {
                    if (mElements[i].profileNum < minProfile)
                        minProfile = mElements[i].profileNum;
                }
            }

            // first lowest tagNum for this vendorId/profileNum
            uint64_t minTagNum = UINT64_MAX;
            size_t lowestIndex;
            for (i = starting; i < mNumEntriesUsed; i++)
            {
                if (mElements[i].vendorId == minVendor && mElements[i].profileNum == minProfile)
                {
                    if (mElements[i].tagNum < minTagNum)
                    {
                        minTagNum   = mElements[i].tagNum;
                        lowestIndex = i;
                    }
                }
            }

            // lowestIndex is the element to move into elements[starting].
            if (lowestIndex != starting)
            {
                //
                VendorReservedElement tmpElement;

                tmpElement             = mElements[starting];
                mElements[starting]    = mElements[lowestIndex];
                mElements[lowestIndex] = tmpElement;
            }
            starting++;
        }
    }

    VendorReservedElement * mElements;
    size_t mMaxSize;            // size of elements array
    size_t mNumEntriesUsed = 0; // elements used
    size_t mCurrentIndex;       // iterating from [0...maxSize -1]
};

} // namespace Credentials
} // namespace chip
