/*
 *******************************************************************************
 *
 *  Copyright 2026 RIEGL Laser Measurement Systems
 *
 *  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.
 *
 *  SPDX-License-Identifier: Apache-2.0
 *
 *******************************************************************************
 */
/*!
 *******************************************************************************
 *
 * \file    graphNode.hpp
 * \author  RIEGL LMS GmbH, Austria
 * \brief   Index graph node
 * \version 2015-10-14/AW: Initial version
 * \version 2018-07-05/AW: Add ID conversion operator function
 * \version 2021-07-09/AW: Add comparison operator and hash function (#3922)
 *
 *******************************************************************************
 */

#ifndef RIEGL_RDB_POINTCLOUD_GRAPHNODE_HPP
#define RIEGL_RDB_POINTCLOUD_GRAPHNODE_HPP

//---< INCLUDES >---------------------------------------------------------------

#include <vector>
#include <cstdlib>
#include <cstdint>
#include <functional>

#include "riegl/rdb/pointcloud/transaction.hpp"

//---< NAMESPACE >--------------------------------------------------------------

namespace riegl {
namespace rdb {
namespace pointcloud {

//---< CLASS GraphNode >--------------------------------------------------------
/*!
 * \brief Graph Node
 *
 * This class represents an index graph node. The index structure is
 * used to organize the point cloud and consists of at least one node.
 *
 * The index space is given by the primary point attribute defined
 * during point cloud database creation (see class CreateSettings).
 *
 * Each graph node covers a certain range of the index space and
 * has a number of sub-nodes (aka. "child nodes"). All child nodes
 * lie within the range of the parent node whereas they are usually
 * smaller. A node without child nodes is called a leaf node. Note
 * that any nodes may overlap in index space as well as all other
 * point dimensions (attributes).
 *
 * This documentation uses the term "branch" for a node and all
 * children and grandchildren up to and including the leaf nodes.
 *
 * \see riegl::rdb::Pointcloud::stat()
 */
class GraphNode
{
public:
    typedef std::uint32_t ID;
    typedef std::uint64_t PointCount;

    ID                     id;              //!< unique node identifier (zero is invalid)
    Transaction::ID        revision;        //!< ID of last transaction that has modified any attribute of this branch
    std::vector<GraphNode> children;        //!< list of child nodes (without grandchildren)
    PointCount             pointCountTotal; //!< total number of points in all leaf nodes of the branch
    PointCount             pointCountNode;  //!< number of points in this node (see notes about LOD)

    //! \brief return node identifier
    operator ID() const { return id; }

public:
    GraphNode();
};

inline bool operator==(const GraphNode &n1, const GraphNode &n2)
{
     return (n1.id == n2.id) && (n1.revision == n2.revision);
}

}}} // namespace riegl::rdb::pointcloud

namespace std
{
    template<>
    struct hash<riegl::rdb::pointcloud::GraphNode>
    {
        std::size_t operator()(const riegl::rdb::pointcloud::GraphNode &node) const
        {
            return std::hash<std::uint64_t>()(
                (std::uint64_t(node.id) << 32) | std::uint64_t(node.revision)
            );
        }
    };
}

#endif // RIEGL_RDB_POINTCLOUD_GRAPHNODE_HPP
