#ifndef __sc_filter_itr__
#define __sc_filter_itr__

#include <string>
#include "itr_equal.hh"
#include "clone_ptr.hh"

namespace autil {
  class ConfigData;
}

namespace afilter {
  
  using namespace std;
  using namespace autil;
  
  class FilterItrRoot;

  class FilterItrPart {
  public: // but don't even think about using
    ClonePtr<FilterItrPart> itr;
  protected:
    FilterItrPart & operator= (const FilterItrPart & other) 
    {itr = other.itr; return *this;}

  public:
    FilterItrPart(FilterItrPart * i) : itr(i) {}
    // i is expected to be allocated with new

    typedef char InValue;
    typedef char OutValue;

    FilterItrPart() {}

    virtual string name() const = 0;
    //: returns a unique name

    virtual double order_num() const = 0;  // between 0 and 1

    virtual char first() = 0;
    //: reads the value of the current char
    // guaranteed to only be called once, after the iterator is 
    // repositioned, inorder to get the current character.

    virtual char next() = 0;
    //: gets the next char
    // returns '\0' if it is at the end

    virtual FilterItrPart * clone() const = 0;
    virtual void assign (const FilterItrPart * other) = 0;
    //:
    // this method is undefined if the types are diffrent

    FilterItrPart * real() {return itr;}
    const FilterItrPart * real() const {return itr;}
    //: returns a reference to the real iterator.  
    // The actual reference is guaranteed not to change.  
    // Its actual value may change if any 
    // non-cost member functions are called.  It is const so that YOU
    // don't change it. It is guaranteed to always be at the current
    // position.  Returns null if this is a terminator.

    virtual ~FilterItrPart() {}

    FilterItrRoot * root() {
      FilterItrPart * i = this; 
      while (i->itr) i = i->itr;
      return (FilterItrRoot *)(i);
    }
    const FilterItrRoot * root() const {
      const FilterItrPart * i = this; 
      while (i->itr) i = i->itr;
      return (const FilterItrRoot *)(i);
    }

    //: returns the root iterator which is the first iterator on
    // on the chain.

    virtual void reset() {}
    //: resets any state information if needed

    virtual void scan(const FilterItrRoot & stop, FilterItrRoot * root) {}
    //: if needed scan ahead
    // It should only scan.  It should not do a restart as the manager class
    // will handle that.  Its real iterator should only change if it actuality
    // scans.
    // It is garentted not to be called right after a restart():
    // undefined: root()->restart(i); scan(j)
    // definded:  root()->restart(i); first(); scan(j)

    /*
      virtual int scan_needed() const {return 0;} // 0 - 10
      //: 
      // 0 for never
      // 5 for not really but could cause errors
      // 10 for always

      virtaul void prescan(const FilterItrPart & start) {}
      virtual int prescan_needed() const {return 0;} // 0 - 10
      // 0 for never
      // 1 for only once
      // 10 for after every little change
    */
  };

  bool operator < (const FilterItrPart & rhs, const FilterItrPart & lhs);

  inline bool operator > (const FilterItrPart & rhs, 
			  const FilterItrPart & lhs) 
  {
    return lhs < rhs;
  }
  
  class FilterItrRoot : public FilterItrPart {
  public:
    FilterItrRoot() : FilterItrPart(0) {}

    virtual void restart(const FilterItrRoot & start) = 0;
    //: restarts with a new iterator 
  
    //// this method is undefined if the types are diffrent
    virtual bool equal(const FilterItrRoot &) const = 0;
  };

  inline bool operator== (const FilterItrRoot &rhs, const FilterItrRoot &lhs) 
  {
    return rhs.equal(lhs);
  }

  inline bool operator!= (const FilterItrRoot &rhs, const FilterItrRoot &lhs) 
  {
    return !rhs.equal(lhs);
  }

  void reset(FilterItrPart *);
  void restart(FilterItrPart *, const FilterItrRoot & start);
  void scan(FilterItrPart *, const FilterItrRoot & stop);
  FilterItrPart * add(FilterItrPart *, FilterItrPart * to_add);
  FilterItrPart * find(FilterItrPart * i, const string & name);
  const FilterItrPart * find(const FilterItrPart * i, const string & name);
  FilterItrPart * get_filter_itr (const string & name, ConfigData & opts);

  template <typename Itr, typename EndF = itr_equal<Itr> > 
  class FilterItrRootClass : public FilterItrRoot
  {
  private:
    Itr  ritr;
    EndF endf;
  public:
    FilterItrRootClass() {}
    FilterItrRootClass(const Itr & i, const EndF & e) 
      : ritr(i), endf(e) {}
    FilterItrRootClass(const Itr & i) 
      : ritr(i) {}
    FilterItrRootClass(const Itr &i, const Itr & e) 
      : ritr(i), endf(EndF(e)) {}  

    FilterItrRootClass * clone() const {return new FilterItrRootClass(*this);}
    void assign(const FilterItrPart * other) 
    {*this= *static_cast<const FilterItrRootClass *>(other);}

    string name() const {return "root";}
    double order_num() const {return -1;}
    char first() {if (endf(ritr)) return '\0'; else return *ritr;}
    char next() {
      ++ritr; 
      if (endf(ritr)) return '\0'; 
      else return *ritr;
    }

    void restart(const FilterItrRoot & start) 
    {
      ritr = static_cast<const FilterItrRootClass &>(start).ritr;
      endf = static_cast<const FilterItrRootClass &>(start).endf;
    }

    FilterItrRoot & operator= (const FilterItrPart & other) 
    {
      ritr = static_cast<const FilterItrRootClass &>(other).ritr; 
      endf = static_cast<const FilterItrRootClass &>(other).endf;
      return *this;
    }
    const Itr & true_itr() const {return ritr;}
  
    bool equal(const FilterItrRoot & other) const {
      return ritr == static_cast<const FilterItrRootClass &>(other).ritr;
    }
  };

  //FIXME: make this way more efficient
  template <typename F>
  class FilterFastItr {
  private:
    ClonePtr<F> fil;
    int          offset_;
    char         cur_char;
  public:
    FilterFastItr() {}
    FilterFastItr(char c, const F *f) 
      : fil(f->clone()), offset_(0), cur_char(c) {}
    FilterFastItr& operator++() 
    {cur_char = fil->next(); ++offset_; return *this;}
    FilterFastItr operator++(int) 
    {FilterFastItr temp = *this; ++*this; return temp;}
    char operator*() const {return cur_char;}

    bool at_end() const {return cur_char == '\0';}

    int offset() const {return offset_;}
  };

  template <typename F>
  bool operator== (const FilterFastItr<F> & rhs, const FilterFastItr<F> & lhs) {
    return *rhs.real()->root() == *lhs.real()->root();
  }

  template <typename F>
  bool operator!= (const FilterFastItr<F> & rhs, const FilterFastItr<F>& lhs) {
    return *rhs.real()->root() != *lhs.real()->root();
  }

  template <typename F>
  struct FilterFastItrEndF {
    bool operator() (const FilterFastItr<F> & i) const {return i.at_end();}
  };
}

#endif


#if 0 // to the end of the file

template <typename Itr, typename EndF>
class FilterItr : public FilterItrBase {
  typedef FilterItrRootClass<Itr,EndF> RootClass;
public:
  FilterItr() {add(new RootClass());}
  
  void restart(const Itr & i)                 {restart(RootClass(i));}
  void restart(const Itr & i, const EndF & e) {restart(RootClass(i,e));}
  void restart(const Itr & i, const Itr & e)  {restart(RootClass(i,e));}
  
  void scan(const Itr & i) {scan(RootClass(i));}
  
  const Itr & real() {
    return static_cast<const RootClass *>(root())->true_itr();
  }
};

class FilterItrBase {
private:
  char                     cur_char;
  ClonePtr<FilterItrPart> itr;
public:
  char operator* () const {return cur_char;}
  bool at_end() const {return cur_char == '\0';}
  void operator++() {cur_char = itr->next();}
  const FilterItrRoot * root() const {return itr->root();}
  void reset();
  void restart(const FilterItrRoot & start);
  void scan(const FilterItrRoot & stop);
  void add(FilterItrPart * to_add);
};

inline bool operator== (const FilterItrBase & rhs, const FilterItrBase & lhs) {
  return *rhs.root() == *lhs.root();
}

inline bool operator!= (const FilterItrBase & rhs, const FilterItrBase & lhs) {
  return *rhs.root() != *lhs.root();
}

#endif

