/*
 *
 *    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();
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
