#ifndef BOOKMARK_TREE_CLASS
#define BOOKMARK_TREE_CLASS

/*****************************************************************************\
*                                                                             *
*  Name   : bookmark_tree                                                     *
*  Author : Chris Koeritz                                                     *
*                                                                             *
*  Purpose:                                                                   *
*                                                                             *
*    Parses a link database in HOOPLE format into tree structure.             *
*                                                                             *
*******************************************************************************
* Copyright (c) 2005-$now By Author.  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.  This is online at:      *
*     http://www.fsf.org/copyleft/gpl.html                                    *
* Please send any updates to: fred@gruntose.com                               *
\*****************************************************************************/

#include <basis/istring.h>
#include <data_struct/amorph.h>
#include <nodes/symbol_tree.h>

// forward.
class inner_mark_tree;
class link_record;
class listo_links;
class symbol_int;
class string_table;

////////////////////////////////////////////////////////////////////////////

class bookmark_tree
{
public:
  bookmark_tree();
  virtual ~bookmark_tree();
  IMPLEMENT_CLASS_NAME("bookmark_tree");

  int read_csv_file(const istring &input_filename);
    // reads the file contents of "input_filename" into this tree.

  static void break_name(const istring &to_break, istring &name,
          istring &nick);
    // breaks a category name into the two components, if they exist.

  static bool magic_category_comparison(const istring &a, const istring &b);
    // compares the two strings "a" and "b" and returns true if either the
    // main name or the nickname matches either.

  inner_mark_tree *process_category(const string_array &items);

  void process_link(const string_array &items);

  void process_comment(const istring &current_line_in);

  inner_mark_tree *find_parent(const istring &parent_name);
    // locates the parent called "parent_name" given the context that
    // we've saved about the last parent.

  // these provide access to the information held about the tree...

  inner_mark_tree &access_root();  // allows access to the root of the tree.

  int link_count() const { return _link_count; }

  int category_count() const { return _category_count; }

// public data members...  currently this is used outside the class.
  int _line_number;  // the current line in the database.

private:
  inner_mark_tree *_mark_tree;  // our tree of categories.
  int _link_count;  // number of links.
  int _category_count;  // number of categories.
  inner_mark_tree *_last_parent;  // the last parent we saw.
  inner_mark_tree *_last_node;  // the last node we touched.
  symbol_int *_links_seen;  // URLs we've seen.
  string_table *_category_names;  // used to enforce uniqueness of categories.
};

////////////////////////////////////////////////////////////////////////////

class link_record
{
public:
  istring _description;
  istring _url;
  int _uid;

  link_record(const istring &description, const istring &url, int uid)
      : _description(description), _url(url), _uid(uid) {}
};

////////////////////////////////////////////////////////////////////////////

class listo_links : public amorph<link_record>
{
public:
  listo_links();

  void add(link_record *new_rec, bool sort = true);

private:
  int _next_index;  // tracks where we've added unsorted items.
};

////////////////////////////////////////////////////////////////////////////

class inner_mark_tree : public nodes::symbol_tree
{
public:
  listo_links _links;  // the list held at this node.
  int _uid;  // the unique identifier of this node.

  inner_mark_tree(const istring &node_name, int uid, int max_bits = 2)
  : nodes::symbol_tree(node_name, max_bits), _uid(uid) {}

};

////////////////////////////////////////////////////////////////////////////

#endif

