/* -----------------------------------------------------------------------------
 * std_list.i
 *
 * SWIG typemaps for std::list.
 * The Java proxy class extends java.util.AbstractSequentialList. The std::list
 * container looks and feels much like a java.util.LinkedList from Java.
 * ----------------------------------------------------------------------------- */

%include <std_common.i>

%{
#include <list>
#include <stdexcept>
%}

%fragment("SWIG_ListSize", "header", fragment="SWIG_JavaIntFromSize_t") {
SWIGINTERN jint SWIG_ListSize(size_t size) {
  jint sz = SWIG_JavaIntFromSize_t(size);
  if (sz == -1)
    throw std::out_of_range("list size is too large to fit into a Java int");
  return sz;
}
}

%javamethodmodifiers std::list::begin "private";
%javamethodmodifiers std::list::insert "private";
%javamethodmodifiers std::list::doSize "private";
%javamethodmodifiers std::list::doPreviousIndex "private";
%javamethodmodifiers std::list::doNextIndex "private";
%javamethodmodifiers std::list::doHasNext "private";

// Match Java style better:
%rename(Iterator) std::list::iterator;

%nodefaultctor std::list::iterator;

namespace std {
  template <typename T> class list {

%typemap(javabase) std::list<T> "java.util.AbstractSequentialList<$typemap(jboxtype, T)>"
%proxycode %{
  public $javaclassname(java.util.Collection c) {
    this();
    java.util.ListIterator<$typemap(jboxtype, T)> it = listIterator(0);
    // Special case the "copy constructor" here to avoid lots of cross-language calls
    for (Object o : c) {
      it.add(($typemap(jboxtype, T))o);
    }
  }

  public int size() {
    return doSize();
  }

  public boolean add($typemap(jboxtype, T) value) {
    addLast(value);
    return true;
  }

  public java.util.ListIterator<$typemap(jboxtype, T)> listIterator(int index) {
    return new java.util.ListIterator<$typemap(jboxtype, T)>() {
      private Iterator pos;
      private Iterator last;

      private java.util.ListIterator<$typemap(jboxtype, T)> init(int index) {
        if (index < 0 || index > $javaclassname.this.size())
          throw new IndexOutOfBoundsException("Index: " + index);
        pos = $javaclassname.this.begin();
	pos = pos.advance_unchecked(index);
        return this;
      }

      public void add($typemap(jboxtype, T) v) {
        // Technically we can invalidate last here, but this makes more sense
        last = $javaclassname.this.insert(pos, v);
      }

      public void set($typemap(jboxtype, T) v) {
        if (null == last) {
          throw new IllegalStateException();
        }
        last.set_unchecked(v);
      }

      public void remove() {
        if (null == last) {
          throw new IllegalStateException();
        }
        $javaclassname.this.remove(last);
        last = null;
      }

      public int previousIndex() {
        return $javaclassname.this.doPreviousIndex(pos);
      }

      public int nextIndex() {
        return $javaclassname.this.doNextIndex(pos);
      }

      public $typemap(jboxtype, T) previous() {
        if (previousIndex() < 0) {
          throw new java.util.NoSuchElementException();
        }
        last = pos;
        pos = pos.previous_unchecked();
        return last.deref_unchecked();
      }

      public $typemap(jboxtype, T) next() {
        if (!hasNext()) {
          throw new java.util.NoSuchElementException();
        }
        last = pos;
        pos = pos.next_unchecked();
        return last.deref_unchecked();
      }

      public boolean hasPrevious() {
        // This call to previousIndex() will be much slower than the hasNext() implementation, but it's simpler like this with C++ forward iterators
        return previousIndex() != -1;
      }

      public boolean hasNext() {
        return $javaclassname.this.doHasNext(pos);
      }
    }.init(index);
  }
%}

  public:
    typedef size_t size_type;
    typedef T value_type;
    typedef T &reference;

    /*
     * We'd actually be better off having the nested class *not* be static in the wrapper
     * output, but this doesn't actually remove the $static from the nested class still.
     * (This would allow us to somewhat simplify the implementation of the ListIterator
     * interface and give "natural" semantics to Java users of the C++ iterator)
     */
    //%typemap(javaclassmodifiers) iterator "public class"
    //%typemap(javainterfaces) iterator "java.util.ListIterator<$typemap(jboxtype, T)>"

    struct iterator {
      %extend {
	void set_unchecked(const T &v) {
	  **$self = v;
	}

	iterator next_unchecked() const {
	  std::list<T>::iterator ret = *$self;
	  ++ret;
	  return ret;
	}

	iterator previous_unchecked() const {
	  std::list<T>::iterator ret = *$self;
	  --ret;
	  return ret;
	}

	T deref_unchecked() const {
	  return **$self;
	}

	iterator advance_unchecked(size_type index) const {
	  std::list<T>::iterator ret = *$self;
	  std::advance(ret, index);
	  return ret;
	}
      }
    };

    list();
    list(const list &other);
    %rename(isEmpty) empty;
    bool empty() const;
    void clear();
    %rename(remove) erase;
    iterator erase(iterator pos);
    %rename(removeLast) pop_back;
    void pop_back();
    %rename(removeFirst) pop_front;
    void pop_front();
    %rename(addLast) push_back;
    void push_back(const T &value);
    %rename(addFirst) push_front;
    void push_front(const T &value);
    iterator begin();
    iterator end();
    iterator insert(iterator pos, const T &value);

    %extend {
      %fragment("SWIG_ListSize");
      list(jint count) throw (std::out_of_range) {
        if (count < 0)
          throw std::out_of_range("list count must be positive");
        return new std::list<T>(static_cast<std::list<T>::size_type>(count));
      }

      list(jint count, const T &value) throw (std::out_of_range) {
        if (count < 0)
          throw std::out_of_range("list count must be positive");
        return new std::list<T>(static_cast<std::list<T>::size_type>(count), value);
      }

      jint doSize() const throw (std::out_of_range) {
        return SWIG_ListSize(self->size());
      }

      jint doPreviousIndex(const iterator &pos) const throw (std::out_of_range) {
        return pos == self->begin() ? -1 : SWIG_ListSize(std::distance(self->begin(), static_cast<std::list<T>::const_iterator>(pos)));
      }

      jint doNextIndex(const iterator &pos) const throw (std::out_of_range) {
        return pos == self->end() ? SWIG_ListSize(self->size()) : SWIG_ListSize(std::distance(self->begin(), static_cast<std::list<T>::const_iterator>(pos)));
      }

      bool doHasNext(const iterator &pos) const {
        return pos != $self->end();
      }
    }
  };
}
