/*
 *
 *    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 = SIZE_MAX;
            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
