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

#ifndef DJ_LIST_H
#define DJ_LIST_H
#include <djType.h>

namespace dj {

// List node.
//
template <class T>
class ListNode {
public:

  ListNode();

  T data;
  
  ListNode * prev, * next;
};

// List iterator.
//
// XXX Temporary lists? What we'd like:
//
// for (ConstListIt<int> it = intList(); it.isValid(); ++it)
//
// What we do now:
//
// const List<int> tmp = intList();
// for (ConstListIt<int> it = tmp; it.isValid(); ++it)
//
template <class T>
class ConstListIt {
public:

  ConstListIt(const ListNode<T> *, const ListNode<T> * stub);
  
  bool isValid() const { return _node != _stub; }
  const T & operator () () const { return _node->data; }
  int count() const { return _count; }

  void next() { _node = _node->next; ++_count; }
  void prev() { _node = _node->prev; ++_count; }
  void operator ++ () { next(); }
  void operator -- () { prev(); }
  
  bool operator == (const ConstListIt &) const;
  bool operator != (const ConstListIt &) const;

protected:

  const ListNode<T> * _node, * _stub;
  int _count;
};
template <class T>
class ListIt : public ConstListIt<T> {
public:

  ListIt(ListNode<T> *, const ListNode<T> * stub);
  
  void operator () (const T &);
  T & operator () ();
  const T & operator () () const;
};

// List.
//
template <class T>
class _List {
public:

  _List();
  _List(const _List<T> &);
  virtual ~_List() = 0;

  // Set.
  //
  virtual void set(const T &, int);
  virtual _List<T> & operator = (const _List<T> &);
  virtual T & operator [] (int);
  virtual void size(int);

  // Get.
  //
  virtual const T & get(int) const;
  virtual const T & operator [] (int) const;
  virtual int size() const { return _stub->size; }

  // Add.
  //
  virtual int insert(const T &, int);
  virtual int insert(const _List<T> &, int);
  virtual int insert(const T *, int index, int size);
  virtual int push(const T &);
  virtual int add(const T &);
  virtual int add(const _List<T> &);
  virtual int add(const T *, int size);
  virtual int add(ConstListIt<T>, ConstListIt<T>);
  virtual void operator += (const _List<T> &);
  virtual void operator += (const T &);

  // Delete.
  //
  virtual const T pop();
  virtual const T shift();
  virtual const T del(int);
  virtual int del(int index, int size);
  virtual void del();

  // Editing.
  //
  virtual int replace(const T &, int index, int size = 1);
  virtual int replace(const _List<T> &, int index, int size = 1);

  // Iterators.
  //
  virtual const ConstListIt<T> start() const;
  virtual const ListIt<T> start();
  virtual const ConstListIt<T> end() const;
  virtual const ListIt<T> end();
  virtual const ConstListIt<T> it(int index) const;
  virtual const ListIt<T> it(int index);
  virtual operator const ConstListIt<T>() const { return start(); }
  virtual operator const ListIt<T>() { return start(); }

private:

  int add(const ListNode<T> *, int size);
  void _del();
  ListNode<T> * node(int);
  const ListNode<T> * node(int) const;
  void detach();
  
  template <class U>
  class StubNode : public ListNode<U> {
  public:
    StubNode();
    int size;
    int ref;
  };
  
  StubNode<T> * _stub;
};
template <class T>
class List : public _List<T> {};

// List types.
//
typedef List<int> IntList;
typedef ListIt<int> IntListIt;
typedef ConstListIt<int> ConstIntListIt;
typedef List<double> FloatList;
typedef ListIt<double> FloatListIt;
typedef ConstListIt<double> ConstFloatListIt;

// Functions.
//
template <class T, class U> void copy(const List<T> &, List<U> *);
template <class T> const List<T> cut(const List<T> &, int index, int size);
template <class T>
const List<T> cut(const ConstListIt<T> &, const ConstListIt<T> &);
template <class T> const List<T> join(const List<List<T> > &);
template <class T> const List<T> join(const List<List<T> > &, const T &);
template <class T> const List<T> join(const List<List<T> > &, const List<T> &);
template <class T> int find(const List<T> &, const T & find, int start = -1);
template <class T>
int findReverse(const List<T> &, const T & find, int start = -1);
template <class T>
const List<T> replace(const List<T> &, const T & find, const T & replace);
template <class T>
const List<T> replace(const List<T> &, const T & find, const List<T> & replace);
template <class T>
const List<List<T> > split(
  const List<T> &, const T & find, bool keepEmpty = false
);
template <class T> const List<T> operator + (const List<T> &, const List<T> &);
template <class T> const List<T> operator + (const List<T> &, const T &);

// Comparison.
//
template <class T> bool operator == (const List<T> &, const List<T> &);
template <class T> bool operator != (const List<T> &, const List<T> &);

}

#include <djList_.h>
#include <djListFnc_.h>
#endif
