/* node.h */

#ifndef NODE__H
#define NODE__H

#include "id.h"
#include <LEDA/dictionary.h>
#include <LEDA/list.h>
#include "id_lookup.h"

/* - dc_node is an extension of dc_label with a list mapping localLabels of 
   children to pointers.  
   - a dc_label or descendant class has a parent wihich is either a dc_node or
   descendant or the root( nil )

   - dc_node is the base class for dc_component

   - on death a dc_node will delete all of its children

   - this header file also includes search functions and functions used to
   perform an operation on all children of a node 
   for seareches see id_lookup.h */

class dc_node : public dc_label {
private:
  tag localTag; /* can be used to assign generic names to implicit/invisible
		   children, but not currently used */

  /* adds child to list and sets child's parentID to this. returns true if 
     adding would result in component loop. */
  bool add_child( dc_label *child ); 

  /* removes child from list. returns true on error 
     ( child not present in list ) */
  bool remove_child( cstring  ); 

  /* called at end of add_child */
  virtual void child_init( dc_label * ) { ; }
  /* at time child_init is called, child's parent pointer will still be 
     old_parent, and will still be in old_parent's list, or if was temporary 
     before, will still be temporary at time of call */

  /* called at start of remove_child */
  virtual void child_cleanup( dc_label * ) { ; }
  /* may still be attached to previous or next parent, so do not do searches or
     access parent */

protected:
  tag get_localTag( void ) { return localTag++; }
  
  /* maps children's label to pointers.  should be private but needed for 
     iteration */
  dictionary<string, dc_label *> child_list;

public:
  dc_node( void );
  dc_node( cstring , dc_node * = nil );
  ~dc_node( void );

  const dc_type type( void ) const { return Node_t; }
  string type_string( void ) const { return "node"; }  

  /*  ostream &display( ostream &stream = cout );
      friend ostream &operator<<( ostream &stream, dc_node &N ) {
      return N.display( stream ); 
      } */

  dc_label *lookup_child( cstring lbl, const bool see_all = false ) const;
  bool child_exists( cstring label ) const;

  /* mostly used for debugging */
  void list_children( ostream &stream = cout ); /* defined in display.cc */

  /* appends all children ids to list.  not efficient */
  void expand( list<dc_label *> & ) const; 

  /* for search descrips see id_lookup.h */
  friend void search_expand( const dc_label *, 
			     queue<search_node *> &search_queue );
  friend dc_label *lookup_relative( cstring , dc_label *, 
				    const bool see_all = false );

  void set_visible_i( const bool );

  /* performs an op on all desc of origin matching a given criterion.  will
     ignore invisible objects if see_all is false */
  friend void for_desc_match( bool criterion( dc_label * ), dc_label *origin,
			      void op( dc_label* ), const bool see_all =false );
  friend void for_desc_match( bool ( dc_label *, void * ), dc_label *, 
			      void ( dc_label *, void * ), void *, 
			      const bool see_all = false );
  friend void for_type_match( bool ( dc_label * ), dc_label *, user_type,
			      void ( dc_label * ), const bool see_all = false );
  friend void for_type_match( bool ( dc_label *, void * ), dc_label *, 
			      user_type, void ( dc_label *, void * ), 
			      void *, const bool see_all = false );

  /* performs op on each child */
  void for_children( void op( dc_label * ), const bool see_all = false );
  void for_children( void op( dc_label *, void * ), void *, 
		     const bool see_all = false );
  void for_children( void op( const dc_label * ), 
		     const bool see_all = false ) const;
  void for_children( void op( const dc_label *, void * ), void *, 
		     const bool see_all = false ) const;

  dc_label *duplicate( dc_node *parent ) const;

  /* following fns need to modify child_list */
  friend dc_label::~dc_label( void );
  friend dc_label::set_label( cstring  );
  friend dc_label::set_parent( dc_node * );
  friend dc_label::set_both( cstring , dc_node * );
};

/* used in iteration loop to duplicate children */
void dup_child( dc_label *child, void *parent ); /* parent cast to dc_node* */

#endif
