#ifndef _COMPOUND_H_
#define _COMPOUND_H_

#include "element.h"

/** The compound class is an abstract class to provide some list features. The simplest implementation is the vector.
*/
class Compound : public Element
{
 private:

  Element * _content;

 protected:

  ostream & printContent(int,ostream&) const;

 public:
  /** empty constructor */
  Compound();

  /** makes a copy of all elements contained in c, using the copy() method */
  Compound(const Compound& c,Type);

  /** calls the scratch() method */
  virtual ~Compound();

  /** removes and(!) deletes all elements from the compound (using the element's remove() method and calling
   * delete). Caution: The table class has an own scratch method, but don't make this method virtual! */
  /* (never make this method virtual: it meant that deleting a table deletes all the references values,
   * at least in theory. When I tried it, it didn't, but just to make sure, it won't do with another compiler
   * just don't make this virtual!) */
  void scratch();

  /** returns the content (usually the first element) of the compound */
  Element * content() const { return _content; }

  /** returns the n'th element of the compound */
  Element * get(int n) const;

  /** returns the successor of e */
  Element * next(Element * e) const;

  /** returns the predecessor of e */
  Element * prev(Element * e) const;

  /** splits the compound before an element w */
  void splitBefore(Element * e) const;

  /** returns the first element of the compound */
  Element * first() const;

  /** returns the last element of the compound */
  Element * last() const;

  /** returns the number of elements */
  int size() const;

  /** returns true if emtpy */
  bool empty() const;

  /** this method appends an element to the compound at the very end. It is declared virtual to allow special compound
   * to implement a more sophisticated add method, e.g. the Part wants to have the events time ordered!
   */
  virtual void add(Element * e);

  /** adds an element e at the beginning of the compound */
  void push(Element * e);

  /** adds an element ne before the element base */
  void insertBefore(Element * ne, Element * base);

  /** adds an element ne after the element base */
  void insertAfter(Element * ne, Element * base) const;

  /** adds an element e at position i */
  void insertAt(int i, Element *e );

  /** This method replaces the elements e1 and e2. e1 has to belong to the content of the compound object.
   * e2 may not(!) be the first element in any compound object. In most cases, e2 is free (does not belong
   * to a compound), but it still works fine, if it is just not the first element in a compound
   */
  void replace(Element * e1, Element * e2);

  /** does not(!) delete the element, but removes it from the list. */
  void remove(Element *);

  /** removes (does not delete!) the first element from the compound and returns it */
  Element * cutFirst();

  /** removes (does not delete!) the last element from the compound and returns it */
  Element * cutLast();

  /** sets the compounds content */
  void setContent(Element*);

  /** overload this, if this element has a presentation, and delegate to it */
  virtual void hide();

  /** overload this, if this element has a presentation, and delegate to it */
  virtual void show();

  /** implement this to define output for each element */
  virtual ostream & print(int,ostream&) const = 0;

  /** implement this to define short output for each element */
  virtual void flush(const char*) const;

  /** implement this to define the copy process for each element */
  virtual Element * copy() const = 0;

  virtual bool isEvent() const { return false; }

  virtual bool isTrack() const { return false; }

};

#endif
