/*
 *
 *    Copyright (c) 2021 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 <app/AttributePathExpandIterator.h>

#include <app-common/zap-generated/att-storage.h>
#include <app/AttributePathParams.h>
#include <app/ConcreteAttributePath.h>
#include <app/EventManagement.h>
#include <app/GlobalAttributes.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPTLVDebug.hpp>
#include <lib/support/CodeUtils.h>
#include <lib/support/DLLUtil.h>
#include <lib/support/logging/CHIPLogging.h>

using namespace chip;

// TODO: Need to make it so that declarations of things that don't depend on generated files are not intermixed in af.h with
// dependencies on generated files, so we don't have to re-declare things here.
// Note: Some of the generated files that depended by af.h are gen_config.h and gen_tokens.h
typedef uint8_t EmberAfClusterMask;

extern uint16_t emberAfEndpointCount(void);
extern uint16_t emberAfIndexFromEndpoint(EndpointId endpoint);
extern uint8_t emberAfClusterCount(EndpointId endpoint, bool server);
extern uint16_t emberAfGetServerAttributeCount(chip::EndpointId endpoint, chip::ClusterId cluster);
extern uint16_t emberAfGetServerAttributeIndexByAttributeId(chip::EndpointId endpoint, chip::ClusterId cluster,
                                                            chip::AttributeId attributeId);
extern chip::EndpointId emberAfEndpointFromIndex(uint16_t index);
extern Optional<ClusterId> emberAfGetNthClusterId(chip::EndpointId endpoint, uint8_t n, bool server);
extern Optional<AttributeId> emberAfGetServerAttributeIdByIndex(chip::EndpointId endpoint, chip::ClusterId cluster,
                                                                uint16_t attributeIndex);
extern uint8_t emberAfClusterIndex(EndpointId endpoint, ClusterId clusterId, EmberAfClusterMask mask);
extern bool emberAfEndpointIndexIsEnabled(uint16_t index);

namespace chip {
namespace app {

AttributePathExpandIterator::AttributePathExpandIterator(ObjectList<AttributePathParams> * aAttributePath)
{
    mpAttributePath = aAttributePath;

    // Reset iterator state
    mEndpointIndex  = UINT16_MAX;
    mClusterIndex   = UINT8_MAX;
    mAttributeIndex = UINT16_MAX;

    static_assert(std::numeric_limits<decltype(mGlobalAttributeIndex)>::max() >= ArraySize(GlobalAttributesNotInMetadata),
                  "Our index won't be able to hold the value we need to hold.");
    static_assert(std::is_same<decltype(mGlobalAttributeIndex), uint8_t>::value,
                  "If this changes audit all uses where we set to UINT8_MAX");
    mGlobalAttributeIndex = UINT8_MAX;

    // Make the iterator ready to emit the first valid path in the list.
    Next();
}

void AttributePathExpandIterator::PrepareEndpointIndexRange(const AttributePathParams & aAttributePath)
{
    if (aAttributePath.HasWildcardEndpointId())
    {
        mEndpointIndex    = 0;
        mEndEndpointIndex = emberAfEndpointCount();
    }
    else
    {
        mEndpointIndex = emberAfIndexFromEndpoint(aAttributePath.mEndpointId);
        // If the given cluster id does not exist on the given endpoint, it will return uint16(0xFFFF), then endEndpointIndex
        // will be 0, means we should iterate a null endpoint set (skip it).
        mEndEndpointIndex = static_cast<uint16_t>(mEndpointIndex + 1);
    }
}

void AttributePathExpandIterator::PrepareClusterIndexRange(const AttributePathParams & aAttributePath, EndpointId aEndpointId)
{
    if (aAttributePath.HasWildcardClusterId())
    {
        mClusterIndex    = 0;
        mEndClusterIndex = emberAfClusterCount(aEndpointId, true /* server */);
    }
    else
    {
        mClusterIndex = emberAfClusterIndex(aEndpointId, aAttributePath.mClusterId, CLUSTER_MASK_SERVER);
        // If the given cluster id does not exist on the given endpoint, it will return uint8(0xFF), then endClusterIndex
        // will be 0, means we should iterate a null cluster set (skip it).
        mEndClusterIndex = static_cast<uint8_t>(mClusterIndex + 1);
    }
}

void AttributePathExpandIterator::PrepareAttributeIndexRange(const AttributePathParams & aAttributePath, EndpointId aEndpointId,
                                                             ClusterId aClusterId)
{
    if (aAttributePath.HasWildcardAttributeId())
    {
        mAttributeIndex          = 0;
        mEndAttributeIndex       = emberAfGetServerAttributeCount(aEndpointId, aClusterId);
        mGlobalAttributeIndex    = 0;
        mGlobalAttributeEndIndex = ArraySize(GlobalAttributesNotInMetadata);
    }
    else
    {
        mAttributeIndex = emberAfGetServerAttributeIndexByAttributeId(aEndpointId, aClusterId, aAttributePath.mAttributeId);
        // If the given attribute id does not exist on the given endpoint, it will return uint16(0xFFFF), then endAttributeIndex
        // will be 0, means we should iterate a null attribute set (skip it).
        mEndAttributeIndex = static_cast<uint16_t>(mAttributeIndex + 1);
        if (mAttributeIndex == UINT16_MAX)
        {
            // Check whether this is a non-metadata global attribute.
            //
            // Default to the max value, which will correspond (after we add 1
            // and overflow to 0 for the max index) to us not going through
            // non-metadata global attributes for this attribute.
            mGlobalAttributeIndex = UINT8_MAX;

            static_assert(ArraySize(GlobalAttributesNotInMetadata) <= UINT8_MAX, "Iterating over at most 256 array entries");

            const uint8_t arraySize = static_cast<uint8_t>(ArraySize(GlobalAttributesNotInMetadata));
            for (uint8_t idx = 0; idx < arraySize; ++idx)
            {
                if (GlobalAttributesNotInMetadata[idx] == aAttributePath.mAttributeId)
                {
                    mGlobalAttributeIndex = idx;
                    break;
                }
            }
            mGlobalAttributeEndIndex = static_cast<uint8_t>(mGlobalAttributeIndex + 1);
        }
    }
}

void AttributePathExpandIterator::ResetCurrentCluster()
{
    // If this is a null iterator, or the attribute id of current cluster info is not a wildcard attribute id, then this function
    // will do nothing, since we won't be expanding the wildcard attribute ids under a cluster.
    VerifyOrReturn(mpAttributePath != nullptr && mpAttributePath->mValue.HasWildcardAttributeId());

    // Otherwise, we will reset the index for iterating the attributes, so we report the attributes for this cluster again. This
    // will ensure that the client sees a coherent view of the cluster from the reports generated by a single (wildcard) attribute
    // path in the request.
    //
    // Note that when Next() returns, we must be in one of the following states:
    // - This is not a wildcard path
    // - We just expanded some attribute id field
    // - We have exhausted all paths
    // Only the second case will happen here since the above check will fail for 1 and 3, so the following Next() call must result
    // in a valid path, which is the first attribute id we will emit for the current cluster.
    mAttributeIndex       = UINT16_MAX;
    mGlobalAttributeIndex = UINT8_MAX;
    Next();
}

bool AttributePathExpandIterator::Next()
{
    for (; mpAttributePath != nullptr; (mpAttributePath = mpAttributePath->mpNext, mEndpointIndex = UINT16_MAX))
    {
        mOutputPath.mExpanded = mpAttributePath->mValue.IsWildcardPath();

        if (mEndpointIndex == UINT16_MAX)
        {
            // Special case: If this is a concrete path, we just return its value as-is.
            if (!mpAttributePath->mValue.IsWildcardPath())
            {
                mOutputPath.mEndpointId  = mpAttributePath->mValue.mEndpointId;
                mOutputPath.mClusterId   = mpAttributePath->mValue.mClusterId;
                mOutputPath.mAttributeId = mpAttributePath->mValue.mAttributeId;

                // Prepare for next iteration
                mEndpointIndex = mEndEndpointIndex = 0;
                return true;
            }

            PrepareEndpointIndexRange(mpAttributePath->mValue);
            mClusterIndex = UINT8_MAX;
        }

        for (; mEndpointIndex < mEndEndpointIndex;
             (mEndpointIndex++, mClusterIndex = UINT8_MAX, mAttributeIndex = UINT16_MAX, mGlobalAttributeIndex = UINT8_MAX))
        {
            if (!emberAfEndpointIndexIsEnabled(mEndpointIndex))
            {
                // Not an enabled endpoint; skip it.
                continue;
            }

            EndpointId endpointId = emberAfEndpointFromIndex(mEndpointIndex);

            if (mClusterIndex == UINT8_MAX)
            {
                PrepareClusterIndexRange(mpAttributePath->mValue, endpointId);
                mAttributeIndex       = UINT16_MAX;
                mGlobalAttributeIndex = UINT8_MAX;
            }

            for (; mClusterIndex < mEndClusterIndex;
                 (mClusterIndex++, mAttributeIndex = UINT16_MAX, mGlobalAttributeIndex = UINT8_MAX))
            {
                // emberAfGetNthClusterId must return a valid cluster id here since we have verified the mClusterIndex does
                // not exceed the mEndClusterIndex.
                ClusterId clusterId = emberAfGetNthClusterId(endpointId, mClusterIndex, true /* server */).Value();
                if (mAttributeIndex == UINT16_MAX && mGlobalAttributeIndex == UINT8_MAX)
                {
                    PrepareAttributeIndexRange(mpAttributePath->mValue, endpointId, clusterId);
                }

                if (mAttributeIndex < mEndAttributeIndex)
                {
                    // GetServerAttributeIdByIdex must return a valid attribute here since we have verified the mAttributeIndex does
                    // not exceed the mEndAttributeIndex.
                    mOutputPath.mAttributeId = emberAfGetServerAttributeIdByIndex(endpointId, clusterId, mAttributeIndex).Value();
                    mOutputPath.mClusterId   = clusterId;
                    mOutputPath.mEndpointId  = endpointId;
                    mAttributeIndex++;
                    // We found a valid attribute path, now return and increase the attribute index for next iteration.
                    // Return true will skip the increment of mClusterIndex, mEndpointIndex and mpAttributePath.
                    return true;
                }
                if (mGlobalAttributeIndex < mGlobalAttributeEndIndex)
                {
                    // Return a path pointing to the next global attribute.
                    mOutputPath.mAttributeId = GlobalAttributesNotInMetadata[mGlobalAttributeIndex];
                    mOutputPath.mClusterId   = clusterId;
                    mOutputPath.mEndpointId  = endpointId;
                    mGlobalAttributeIndex++;
                    return true;
                }
                // We have exhausted all attributes of this cluster, continue iterating over attributes of next cluster.
            }
            // We have exhausted all clusters of this endpoint, continue iterating over clusters of next endpoint.
        }
        // We have exhausted all endpoints in this cluster info, continue iterating over next cluster info item.
    }

    // Reset to default, invalid value.
    mOutputPath = ConcreteReadAttributePath();
    return false;
}
} // namespace app
} // namespace chip
