#include <iostream>
#include <iterator>
#include <functional>

#include "substr_repl.hh"

namespace afilter {

  template <typename FItrLHS, typename ItrLHSEndF, 
    typename FItrRHS, typename ItrRHSEndF>
  bool lt_fs_(FItrLHS &lhs, const ItrLHSEndF & lhs_endf, 
	      FItrRHS &rhs, const ItrRHSEndF & rhs_endf)
  {
    while (!rhs_endf(rhs) && !lhs_endf(lhs) && *rhs == *lhs) 
      ++rhs, ++lhs;
  
    if (lhs_endf(lhs)) 
      if (rhs_endf(rhs))    // lhs == end && rhs == end
	return false;
      else                  // lhs == end && rhs != end
	return true;
    else if (rhs_endf(rhs)) // lhs != end && rhs == end
      return false;
    else                    // lhs != end && rhs != end
      return *lhs < *rhs;
  }

  template <class ItrStr, class RItr>
  struct find_substr_return {
    RItr    loc;
    ItrStr  str_loc;
    find_substr_return() {}
    find_substr_return(RItr l, ItrStr sl) : loc(l), str_loc(sl) {}
    find_substr_return(RItr l) : loc(l) {}
  };

  template <typename ItrStr, typename ItrStrEndF, typename RItr>
  find_substr_return<ItrStr, RItr>
  find_substr (ItrStr str_begin, const ItrStrEndF & str_endf, 
	       RItr first, RItr last)
  {
    typename iterator_traits<RItr>::difference_type 
      low  = 0,
      mid,
      high = last - first -1;
  
    RItr                     middle;
    typename iterator_traits<RItr>::value_type::Iterator  middle_begin;
    typename iterator_traits<RItr>::value_type::Endf      middle_endf;
    ItrStr                   str_loc;

    bool lessthan;
  
    typedef find_substr_return<ItrStr, RItr> Ret;

    while (low <= high) {
      mid = (low+high)/2;
      middle = first + mid;
      middle_begin = (*middle).begin();
      middle_endf  = (*middle).endf();
      str_loc      = str_begin;
      lessthan = lt_fs_(middle_begin, middle_endf, str_loc, str_endf);
      if (middle_endf(middle_begin))
	return Ret(middle, str_loc);
      if (lessthan)
	low = mid+1;
      else
	high = mid-1;
    }
    return Ret(last);
  }

  template <typename T>
  bool SubstrRepl<T>::fill(InValue c, Itr * i, Buffer * buffer) {
    find_substr_return<FilterFastItr<Itr>, const_iterator> 
      ret = find_substr(FilterFastItr<Itr>(c,i), FilterFastItrEndF<Itr>(), 
			begin(), end());
    if (ret.loc != end()) {
      add_to_buffer(*buffer, ret.loc->value, SingleMulti());
      for (int k = 1; k !=  ret.str_loc.offset(); ++k)
	i->next();
      return true;
    } else {
      return false;
    }
  }
}

#if 0 // to end of file
  struct tt{
    char * key;
    char * value_;
    const char * begin() const {return key;}
    null_end_t   end()   const {return null_end;}
    char *       value() const {return value_;}
  };

  class tts {
    tt * begin_;
    tt * end_;
  public:
    typedef tt * iterator;
    typedef const tt * const_iterator;
    tt * begin() const {return begin_;}
    tt * end() const {return end_;}
    const char * name() {return "Map";}
    tts(tt * b, tt * e) : begin_(b), end_(e) {}
  };

  int main() {
    tt items[] = {
      {"^a", "A"},
	{"^b", "B"},
	  {"^c", "C"},
	    {"^d", "D"},
	      {"^e", "E"},
		{"aa", "a.a"},
		  {"ae", "a.e"},
		    {"dd", "d.d"}
    };

    tt * end = items + sizeof(items)/sizeof(tt);

    const char *str = " ^a^b^c^d^e ^aa^bb^cc^dd^ee ae aa aa ae dd ^aid ^dog";

    repl_iterator<MapRepl<const char *, cstr_buffer, null_end_t, tts> >
      repl(tts(items, end));

    repl.restart(str, null_end);

    while (!repl.at_end()) {
      cout << *repl;
      ++repl;
    }

    return 0;
  }
#endif
