/// QasTools: Desktop toolset for the Linux sound system ALSA.
/// \copyright See COPYING file.

#pragma once

#include <array>
#include <cassert>
#include <vector>

/// @brief Static_Tree_Node
///
class Static_Tree_Node
{
  public:
  // -- Construction

  Static_Tree_Node () = default;

  ~Static_Tree_Node () = default;

  // -- Attributes
  std::size_t parent_idx = 0;
  std::size_t self_idx = 0;
  std::size_t children_idx = 0;
};

/// @brief Static_Tree
///
class Static_Tree : public std::vector< Static_Tree_Node >
{
  public:
  using Node = Static_Tree_Node;

  public:
  // -- Construction

  Static_Tree ();

  ~Static_Tree ();

  void
  reset ();

  // -- Node access

  Node *
  node ( std::size_t idx_n )
  {
    if ( idx_n < size () ) {
      return &operator[] ( idx_n );
    }
    return nullptr;
  }

  const Node *
  node ( std::size_t idx_n ) const
  {
    if ( idx_n < size () ) {
      return &operator[] ( idx_n );
    }
    return nullptr;
  }

  // -- Root node

  const Node *
  root_node () const
  {
    return node ( 0 );
  }

  Node *
  root_node ()
  {
    return node ( 0 );
  }

  /// @brief Checks if the node is the root node
  bool
  is_root ( const Node * node_n ) const
  {
    return ( node_n->self_idx == 0 );
  }

  // -- Parent node

  const Node *
  parent_node ( const Node * node_n ) const;

  Node *
  parent_node ( const Node * node_n );

  // -- Child node

  const Node *
  child_node ( const Node * node_n, std::size_t child_n ) const;

  Node *
  child_node ( const Node * node_n, std::size_t child_n );

  // -- Statistics

  /// @brief Depth inside the tree. 0 is the root node.
  std::size_t
  depth ( const Node * node_n ) const;

  /// @brief Computes the child index of node_n
  std::size_t
  row ( const Node * node_n ) const;

  /// @brief The number of children of this node
  std::size_t
  num_children ( const Node * node_n ) const;

  /// @brief Calculates the rootline starting from the node downwards
  void
  rootline ( const Node * node_n, std::vector< std::size_t > & rows_n ) const;

  /// @brief Appends the number of children to the node.
  ///        This invalidates all Node pointers.
  /// @return The begin and end indices of the children
  std::array< std::size_t, 2 >
  append_children ( std::size_t node_idx_n, std::size_t num_n );
};
