/*------------------------------------------------------------------------------
 src/lib/dj/djListFnc_.h
 
 Copyright (c) 2004-2006 Darby Johnston.
 All rights reserved.
 Use is subject to license terms.
------------------------------------------------------------------------------*/

namespace dj {

template <class T, class U>
inline void copy(const List<T> & in, List<U> * out)
{
  for (ConstListIt<T> it = in; it.isValid(); ++it)
    out->add(it());
}

template <class T>
inline const List<T> cut(const List<T> & in, int index, int size)
{
  List<T> out;
  out.add(in.it(index), in.it(index + size));
  return out;
}

template <class T>
inline const List<T> cut(const ConstListIt<T> & a, const ConstListIt<T> & b)
{
  List<T> out;
  ConstListIt<T> tmp = b;
  ++tmp;
  out.add(a, tmp);
  return out;
}

template <class T>
inline const List<T> join(const List<List<T> > & in)
{
  List<T> out;
  for (ConstListIt<List<T> > it = in; it.isValid(); ++it)
    out.add(it());
  return out;
}

template <class T>
inline const List<T> join(const List<List<T> > & in, const T & separator)
{
  return join(in, List<T>() + separator);
}

template <class T>
inline const List<T> join(const List<List<T> > & in, const List<T> & separator)
{
  List<T> out;
  for (ConstListIt<List<T> > it = in; it.isValid();) {
    out.add(it());
    ++it;
    if (it.isValid())
      out.add(separator);
  }
  return out;
}

template <class T>
inline int find(const List<T> & in, const T & find, int start)
{
  if (start < 0) start = 0;
  else if (start >= in.size()) return -1;
  
  for (ConstListIt<T> it = in; it.isValid(); ++it)
    if (it.count() >= start && find == it()) return it.count();
  return -1;
}

template <class T>
inline int findReverse(const List<T> & in, const T & find, int start)
{
  if (start < 0) start = in.size() - 1;
  else if (start >= in.size()) return -1;
  
  int i = in.size() - 1;
  for (ConstListIt<T> it = in.end(); it.isValid(); --it, --i)
    if (i <= start && find == it()) return i;
  return -1;
}

template <class T>
inline const List<T> replace(
  const List<T> & in, const T & find, const T & replace
) {
  return replace(in, find, List<T>() + replace);
}

template <class T>
inline const List<T> replace(
  const List<T> & in, const T & find, const List<T> & replace
) {
  List<T> out;
  for (ConstListIt<T> it = in; it.isValid(); ++it)
    if (find == it())
      out += replace;
    else
      out += it();
  return out;
}

template <class T>
inline const List<T> operator + (const List<T> & a, const List<T> & b)
{
  List<T> out(a);
  out.add(b);
  return out;
}

template <class T>
inline const List<T> operator + (const List<T> & a, const T & b)
{
  List<T> out(a);
  out.add(b);
  return out;
}

template <class T>
inline const List<List<T> > split(
  const List<T> & in, const T & find, bool keepEmpty
) {
  List<List<T> > out;
  out += List<T>();
  int current = 0;
  for (ConstListIt<T> it = in; it.isValid(); ++it)
    if (find == it()) {
      if (keepEmpty || (! keepEmpty && out[current].size())) {
        out += List<T>();
        ++current;
      }
    } else
      out[current] += it();
  if (! keepEmpty)
    if (out.size())
      if (! out[out.size() - 1].size())
        out.shift();
  return out;
}

template <class T>
inline bool operator == (const List<T> & a, const List<T> & b)
{
  if (a.size() != b.size()) return false;
  for (ConstListIt<T> itA = a, itB = b; itA.isValid(); ++itA, ++itB)
    if (itA() != itB()) return false;
  return true;
}

template <class T>
inline bool operator != (const List<T> & a, const List<T> & b)
  { return ! (a == b); }

}
