/*
 *    Copyright (c) 2024 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/GlobalAttributes.h>
#include <app/data-model-provider/MetadataLookup.h>
#include <app/data-model-provider/MetadataTypes.h>
#include <lib/core/DataModelTypes.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ReadOnlyBuffer.h>

#include <optional>

using namespace chip::app::DataModel;

namespace chip {
namespace app {

AttributePathExpandIterator::AttributePathExpandIterator(DataModel::Provider * dataModel, Position & position) :
    mDataModelProvider(dataModel), mPosition(position)
{}

bool AttributePathExpandIterator::AdvanceOutputPath()
{
    /// Output path invariants
    ///    - kInvalid* constants are used to define "no value available (yet)" and
    ///      iteration loop will fill the first value when such a value is seen (fixed for non-wildcard
    ///      or iteration-based in case of wildcards).
    ///    - Iteration of the output path is done in order: first endpoint, then cluster, then attribute.
    /// Processing works like:
    ///    - Initial state is kInvalidEndpointId/kInvalidClusterId/kInvalidAttributeId
    ///    - First loop pass fills-in endpointID, followed by clusterID, followed by attributeID
    ///    - Whenever one level is done iterating (there is no "next") the following
    ///      "higher path component" is updated:
    ///         - once a valid path exists, try to advance attributeID
    ///         - if attributeID fails to advance, try to advance clusterID (and restart attributeID)
    ///         - if clusterID fails to advance, try to advance endpointID (and restart clusterID)
    ///         - if endpointID fails to advance, iteration is done
    while (true)
    {
        if (mPosition.mOutputPath.mClusterId != kInvalidClusterId)
        {
            std::optional<AttributeId> nextAttribute = NextAttributeId();
            if (nextAttribute.has_value())
            {
                mPosition.mOutputPath.mAttributeId = *nextAttribute;
                mPosition.mOutputPath.mExpanded    = mPosition.mAttributePath->mValue.IsWildcardPath();
                return true;
            }
        }

        // no valid attribute, try to advance the cluster, see if a suitable one exists
        if (mPosition.mOutputPath.mEndpointId != kInvalidEndpointId)
        {
            std::optional<ClusterId> nextCluster = NextClusterId();
            if (nextCluster.has_value())
            {
                // A new cluster ID is to be processed. This sets the cluster ID to the new value and
                // ALSO resets the attribute ID to "invalid", to trigger an attribute set/expansion from
                // the beginning.
                mPosition.mOutputPath.mClusterId   = *nextCluster;
                mPosition.mOutputPath.mAttributeId = kInvalidAttributeId;
                continue;
            }
        }

        // No valid cluster, try advance the endpoint, see if a suitable one exists.
        std::optional<EndpointId> nextEndpoint = NextEndpointId();
        if (nextEndpoint.has_value())
        {
            // A new endpoint ID is to be processed. This sets the endpoint ID to the new value and
            // ALSO resets the cluster ID to "invalid", to trigger a cluster set/expansion from
            // the beginning.
            mPosition.mOutputPath.mEndpointId = *nextEndpoint;
            mPosition.mOutputPath.mClusterId  = kInvalidClusterId;
            continue;
        }
        return false;
    }
}

bool AttributePathExpandIterator::Next(ConcreteAttributePath & path)
{
    while (mPosition.mAttributePath != nullptr)
    {
        if (AdvanceOutputPath())
        {
            path = mPosition.mOutputPath;
            return true;
        }
        mPosition.mAttributePath = mPosition.mAttributePath->mpNext;
        mPosition.mOutputPath    = ConcreteReadAttributePath(kInvalidEndpointId, kInvalidClusterId, kInvalidAttributeId);
    }

    return false;
}

bool AttributePathExpandIterator::IsValidAttributeId(AttributeId attributeId)
{
    switch (attributeId)
    {
    case Clusters::Globals::Attributes::GeneratedCommandList::Id:
    case Clusters::Globals::Attributes::AcceptedCommandList::Id:
    case Clusters::Globals::Attributes::AttributeList::Id:
        return true;
    default:
        break;
    }

    DataModel::AttributeFinder finder(mDataModelProvider);

    const ConcreteAttributePath attributePath(mPosition.mOutputPath.mEndpointId, mPosition.mOutputPath.mClusterId, attributeId);
    return finder.Find(attributePath).has_value();
}

std::optional<AttributeId> AttributePathExpandIterator::NextAttributeId()
{
    if (mPosition.mOutputPath.mAttributeId == kInvalidAttributeId)
    {
        // Attribute ID is tied to attribute index. If no attribute id is available yet
        // this means the index is invalid. Processing logic in output advance only resets
        // attribute ID to invalid when resetting iteration.
        mAttributeIndex = kInvalidIndex;
    }

    if (mAttributeIndex == kInvalidIndex)
    {
        // start a new iteration of attributes on the current cluster path.
        mAttributes = mDataModelProvider->AttributesIgnoreError(mPosition.mOutputPath);

        if (mPosition.mOutputPath.mAttributeId != kInvalidAttributeId)
        {
            // Position on the correct attribute if we have a start point
            mAttributeIndex = 0;
            while ((mAttributeIndex < mAttributes.size()) &&
                   (mAttributes[mAttributeIndex].attributeId != mPosition.mOutputPath.mAttributeId))
            {
                mAttributeIndex++;
            }
        }
    }

    if (mPosition.mOutputPath.mAttributeId == kInvalidAttributeId)
    {
        if (!mPosition.mAttributePath->mValue.HasWildcardAttributeId())
        {
            // The attributeID is NOT a wildcard (i.e. it is fixed).
            //
            // For wildcard expansion, we validate that this is a valid attribute for the given
            // cluster on the given endpoint. If not a wildcard expansion, return it as-is.
            if (mPosition.mAttributePath->mValue.IsWildcardPath())
            {
                if (!IsValidAttributeId(mPosition.mAttributePath->mValue.mAttributeId))
                {
                    return std::nullopt;
                }
            }
            return mPosition.mAttributePath->mValue.mAttributeId;
        }
        mAttributeIndex = 0;
    }
    else
    {
        mAttributeIndex++;
    }

    // Advance the existing attribute id if it can be advanced.
    VerifyOrReturnValue(mPosition.mAttributePath->mValue.HasWildcardAttributeId(), std::nullopt);

    if (mAttributeIndex < mAttributes.size())
    {
        return mAttributes[mAttributeIndex].attributeId;
    }

    return std::nullopt;
}

std::optional<ClusterId> AttributePathExpandIterator::NextClusterId()
{
    if (mPosition.mOutputPath.mClusterId == kInvalidClusterId)
    {
        // Cluster ID is tied to cluster index. If no cluster id available yet
        // this means index is invalid. Processing logic in output advance only resets
        // cluster ID to invalid when resetting iteration.
        mClusterIndex = kInvalidIndex;
    }

    if (mClusterIndex == kInvalidIndex)
    {
        // start a new iteration on the current endpoint
        mClusters = mDataModelProvider->ServerClustersIgnoreError(mPosition.mOutputPath.mEndpointId);

        if (mPosition.mOutputPath.mClusterId != kInvalidClusterId)
        {
            // Position on the correct cluster if we have a start point
            mClusterIndex = 0;
            while ((mClusterIndex < mClusters.size()) && (mClusters[mClusterIndex].clusterId != mPosition.mOutputPath.mClusterId))
            {
                mClusterIndex++;
            }
        }
    }

    if (mPosition.mOutputPath.mClusterId == kInvalidClusterId)
    {

        if (!mPosition.mAttributePath->mValue.HasWildcardClusterId())
        {
            // The clusterID is NOT a wildcard (i.e. is fixed).
            //
            // For wildcard expansion, we validate that this is a valid cluster for the endpoint.
            // If non-wildcard expansion, we return as-is.
            if (mPosition.mAttributePath->mValue.IsWildcardPath())
            {
                const ClusterId clusterId = mPosition.mAttributePath->mValue.mClusterId;

                bool found = false;
                for (auto & entry : mClusters)
                {
                    if (entry.clusterId == clusterId)
                    {
                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    return std::nullopt;
                }
            }

            return mPosition.mAttributePath->mValue.mClusterId;
        }
        mClusterIndex = 0;
    }
    else
    {
        mClusterIndex++;
    }

    VerifyOrReturnValue(mPosition.mAttributePath->mValue.HasWildcardClusterId(), std::nullopt);
    VerifyOrReturnValue(mClusterIndex < mClusters.size(), std::nullopt);

    return mClusters[mClusterIndex].clusterId;
}

std::optional<EndpointId> AttributePathExpandIterator::NextEndpointId()
{
    if (mEndpointIndex == kInvalidIndex)
    {
        // index is missing, have to start a new iteration
        mEndpoints = mDataModelProvider->EndpointsIgnoreError();

        if (mPosition.mOutputPath.mEndpointId != kInvalidEndpointId)
        {
            // Position on the correct endpoint if we have a start point
            mEndpointIndex = 0;
            while ((mEndpointIndex < mEndpoints.size()) && (mEndpoints[mEndpointIndex].id != mPosition.mOutputPath.mEndpointId))
            {
                mEndpointIndex++;
            }
        }
    }

    if (mPosition.mOutputPath.mEndpointId == kInvalidEndpointId)
    {
        if (!mPosition.mAttributePath->mValue.HasWildcardEndpointId())
        {
            return mPosition.mAttributePath->mValue.mEndpointId;
        }

        // start from the beginning
        mEndpointIndex = 0;
    }
    else
    {
        mEndpointIndex++;
    }

    VerifyOrReturnValue(mPosition.mAttributePath->mValue.HasWildcardEndpointId(), std::nullopt);
    VerifyOrReturnValue(mEndpointIndex < mEndpoints.size(), std::nullopt);

    return mEndpoints[mEndpointIndex].id;
}

} // namespace app
} // namespace chip
