/***************************************************************************

    source::worx xtree
    Copyright © 2024-2025 c.holzheuer
    christoph.holzheuer@gmail.com

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

***************************************************************************/


#ifndef znode_iterator_H
#define znode_iterator_H

#include <iterator>



namespace znode
{
  template<typename T>
  struct znode_iterator
  {
    using iterator_category = std::forward_iterator_tag;
    using difference_type   = std::ptrdiff_t;
    using value_type        = T;
    using pointer           = T*;  // or also value_type*
    using reference         = T&;  // or also value_type&

    znode_iterator()
        : _root{},_node{}
    {}

    znode_iterator(pointer node)
        : _root{node},_node{node}
    {}

    void set_node(pointer node)
    {
      _root = node;
      _node = node;
    }

    pointer get() // const
    {
      return _node;
    }

    int level() // const
    {
      return _level;
    }

    pointer operator->()
    {
      return _node;
    }

    reference operator*()
    {
      return *(operator->());
    }

    operator bool() const
    {
      return _node != nullptr;
    }

    // Prefix increment
    znode_iterator& operator++()
    {
      if( !_node )
        return *this;

      // depth first: do we have children?
      if( _node->has_children() )
      {
        _node = _node->first_child().get();
        _level++;
        return *this;
      }

      // no children, so we take siblings
      pointer tmp = _node->sibling().get();
      pointer nxt = _node->parent().get();

      while( !tmp && nxt )
      {
        tmp = nxt->sibling().get();
        if( nxt == _root )
        {
          //qDebug() << " ouch ";
          _node = nullptr;
          return *this;
        }
        _level--;
        nxt = nxt->parent().get();
      }

      _node = tmp;
      return *this;

    }

    // Postfix increment
    znode_iterator operator++(int) { znode_iterator tmp = *this; ++(*this); return tmp; }

    friend bool operator== (const znode_iterator& a, const znode_iterator& b) { return a._node == b._node; };
    friend bool operator!= (const znode_iterator& a, const znode_iterator& b) { return a._node != b._node; };

  protected:

    pointer _root{};
    pointer _node{};
    int     _level{0};

  };

}

#endif // znode_iterator_H
