
#ifndef TOC_TABLE_H
#define TOC_TABLE_H

#include <string>
#include "../Util/TeX_atom.h"
#include "../Page_no/Page_number.h"
#include "../Page_no/PS_page_numbering.h"
#include "Sect_level.h"
#include "../PDF/PDF.h"

// ---------------------------------------------------------------------
// The book's table of contents.
// ---------------------------------------------------------------------

namespace TOC {
  using Page_no::Book_part;
  using Page_no::PREFACE;
  using Page_no::BODY;
  using Page_no::Page_number;
  class Item;
  class Table;
  // The function next_in_sequence() lets one treat a tree of TOC_items
  // as a flat sequence.  As the name suggests, for each TOC_item in the
  // sequence, next_in_sequence() returns a pointer to the next
  // TOC_item, or null if none is next.  It flattens the sequence
  // depth-first.  Beginning at the tree's root and following the
  // sequence therefrom, calling next_in_sequence() repeatedly, one
  // eventually encounters each TOC_item in the tree exactly once.
  Item *next_in_seq( const Item &item, bool descend = true );
  int count_children_recursively( const Item &item );
  int count_items( const Table &table );
  enum Offset_mode {
    OFFSET_RELATIVE = 0,
    OFFSET_ABSOLUTE
  };
  std::string pdf_object_str(
    const PDF::PDF &pdf,
    const Page_no::PS_page_numbering &nog,
    const Item &item,
    const int offset = 0,
    const Offset_mode offset_mode = OFFSET_RELATIVE
  );
}

class TOC::Item {
  private:
    Sect_level level1;
    std::string sect_no1;
    std::string title1;
    Page_number i_page1;
    const int i1;
    void clear_obj();
    void init( const Util::TeX_atom_nonterminal &atom );
  public:
    struct Exc {};
    // One could hide the pointers the next line defines,
    // but to what purpose?  The standard C++ practice of hiding
    // information seems unhelpful in this particular case.
    Item *parent, *prev, *next, *first, *last;
    Sect_level  level  () const { return level1  ; }
    std::string sect_no() const { return sect_no1; }
    std::string title  () const { return title1  ; }
    Page_number i_page () const { return i_page1 ; }
    int         i      () const { return i1      ; }
    explicit Item(
      const Util::TeX_atom_nonterminal &atom,
      const int i0 = 0
    ) : i1(i0) {
      init( atom );
    }
    explicit Item(
      const std::string &line,
      const int i0 = 0
    ) : i1(i0) {
      init( Util::TeX_atom_nonterminal( line ) );
    }
    Item() : i1(0) { clear_obj(); }
    int delete_children();
};

class TOC::Table {
  private:
    Item *root1;
  public:
    Item *root() const { return root1; }
    explicit Table( const std::string &filename_toc );
    Table();
    ~Table();
};

// One could define copy constructors, copy assignors, etc., but for the
// purpose at hand such do not seem to be needed.

#endif

