/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _DECAF_UTIL_STLLIST_H_
#define _DECAF_UTIL_STLLIST_H_

#include <list>
#include <algorithm>
#include <memory>
#include <decaf/lang/exceptions/UnsupportedOperationException.h>
#include <decaf/util/NoSuchElementException.h>
#include <decaf/lang/exceptions/IndexOutOfBoundsException.h>
#include <decaf/util/Config.h>
#include <decaf/util/Iterator.h>
#include <decaf/util/ListIterator.h>
#include <decaf/util/List.h>
#include <decaf/util/AbstractList.h>

namespace decaf {
namespace util {

    /**
     * List class that wraps the STL list object to provide a simpler interface and
     * additional methods not provided by the STL type.
     */
    template <typename E>
    class StlList : public decaf::util::AbstractList<E> {
    private:

        std::list<E> values;

    private:

        class StlListIterator : public ListIterator<E> {
        private:

            typename std::list<E>::iterator current;
            typename std::list<E>::iterator prev;
            typename std::list<E>* list;

        private:

            StlListIterator(const StlListIterator&);
            StlListIterator operator= (const StlListIterator&);

        public:

            StlListIterator(typename std::list<E>* list, int index) :
                current(list->begin()), prev(list->end()), list(list) {

                if (index < (int) list->size()) {
                    std::advance(this->current, index);
                } else {
                    this->current = list->end();
                }
            }

            virtual ~StlListIterator() {}

            virtual E next() {
                if (this->current == list->end()) {
                    throw NoSuchElementException(
                        __FILE__, __LINE__,
                        "List::Iterator::next - No more elements to return");
                }

                this->prev = this->current;
                return *(this->current++);
            }

            virtual bool hasNext() const {
                return ( this->current != list->end() );
            }

            virtual void remove() {
                if (this->prev == list->end()) {
                    throw lang::exceptions::IllegalStateException(
                        __FILE__, __LINE__,
                        "List::Iterator::remove - Invalid State to call remove");
                }

                this->list->erase(this->prev);
                this->prev = this->list->end();
            }

            virtual void add(const E& e) {
                this->list->insert(this->current, e);
            }

            virtual void set(const E& e) {
                if (this->current == list->end()) {
                    this->list->insert(this->current, e);
                } else {
                    *(this->current) = e;
                }
            }

            virtual bool hasPrevious() const {
                return (this->current != this->list->begin());
            }

            virtual E previous() {
                if (this->current == this->list->begin()) {
                    throw NoSuchElementException(
                        __FILE__, __LINE__,
                        "List::ListIterator::previous - No Previous element." );
                }

                typename std::list<E>::const_iterator iter = this->current;
                return *(iter--);
            }

            virtual int nextIndex() const {
                if (this->current == this->list->end()) {
                    return (int) this->list->size();
                }

                return (int) std::distance(this->list->begin(), this->current);
            }

            virtual int previousIndex() const {
                if (this->current == this->list->begin()) {
                    return -1;
                }

                return (int) std::distance(this->list->begin(), this->current) - 1;
            }
        };

        class ConstStlListIterator : public decaf::util::ListIterator<E> {
        private:

            typename std::list<E>::const_iterator current;
            typename std::list<E>::const_iterator prev;
            const typename std::list<E>* list;

        private:

            ConstStlListIterator(const ConstStlListIterator&);
            ConstStlListIterator operator= (const ConstStlListIterator&);

        public:

            ConstStlListIterator(const typename std::list<E>* list, int index) :
                ListIterator<E>(), current(list->begin()), prev(list->end()), list( list) {

                if (index < (int) list->size()) {
                    std::advance(this->current, index);
                } else {
                    this->current = list->end();
                }
            }

            virtual ~ConstStlListIterator() {}

            virtual E next() {
                if (this->current == list->end()) {
                    throw NoSuchElementException(
                        __FILE__, __LINE__,
                        "List::Iterator::next - No more elements to return");
                }

                this->prev = this->current;
                return *(this->current++);
            }

            virtual bool hasNext() const {
                return (this->current != list->end());
            }

            virtual void remove() {

                throw lang::exceptions::UnsupportedOperationException(
                    __FILE__, __LINE__,
                    "List::ListIterator::remove - Const Iterator.");
            }

            virtual void add(const E& e DECAF_UNUSED) {

                throw lang::exceptions::UnsupportedOperationException(
                    __FILE__, __LINE__,
                    "List::ListIterator::add - Const Iterator.");
            }

            virtual void set(const E& e DECAF_UNUSED) {

                throw lang::exceptions::UnsupportedOperationException(
                    __FILE__, __LINE__,
                    "List::ListIterator::set - Const Iterator.");
            }

            virtual bool hasPrevious() const {
                return (this->current != this->list->begin());
            }

            virtual E previous() {
                if (this->current == this->list->begin()) {
                    throw NoSuchElementException(
                        __FILE__, __LINE__,
                        "List::ListIterator::previous - No Previous element.");
                }

                typename std::list<E>::const_iterator iter = this->current;
                return *(iter--);
            }

            virtual int nextIndex() const {
                if (this->current == this->list->end()) {
                    return (int) this->list->size();
                }

                return (int) std::distance(this->list->begin(), this->current);
            }

            virtual int previousIndex() const {
                if (this->current == this->list->begin()) {
                    return -1;
                }

                return (int) std::distance(this->list->begin(), this->current) - 1;
            }
        };

    public:

        /**
         * Default constructor - does nothing.
         */
        StlList() : AbstractList<E>(), values() {}

        /**
         * Copy constructor - copies the content of the given set into this
         * one.
         * @param source The source set.
         */
        StlList(const StlList& source) : AbstractList<E>(), values() {
            copy(source);
        }

        /**
         * Copy constructor - copies the content of the given set into this
         * one.
         * @param source The source set.
         */
        StlList(const Collection<E>& source) : AbstractList<E>(), values() {
            AbstractList<E>::copy(source);
        }

        virtual ~StlList() {}

        /**
         * {@inheritDoc}
         */
        virtual bool equals(const Collection<E>& collection) const {

            const StlList<E>* listptr = dynamic_cast<const StlList<E>*>(&collection);
            if (listptr == NULL) {
                return AbstractList<E>::equals(collection);
            }

            return this->values == listptr->values;
        }

        /**
         * {@inheritDoc}
         */
        virtual void copy(const Collection<E>& collection) {

            const StlList<E>* listptr = dynamic_cast<const StlList<E>*>(&collection);
            if (listptr == NULL) {
                AbstractList<E>::copy(collection);
                return;
            }

            this->values.clear();
            this->values = listptr->values;
        }

        /**
         * {@inheritDoc}
         */
        virtual Iterator<E>* iterator() {
            return new StlListIterator(&values, 0);
        }
        virtual Iterator<E>* iterator() const {
            return new ConstStlListIterator(&values, 0);
        }

        /**
         * {@inheritDoc}
         */
        virtual ListIterator<E>* listIterator() {
            return new StlListIterator(&values, 0);
        }
        virtual ListIterator<E>* listIterator() const {
            return new ConstStlListIterator(&values, 0);
        }

        /**
         * {@inheritDoc}
         */
        virtual ListIterator<E>* listIterator(int index) {

            if (index < 0 || index > this->size()) {
                throw decaf::lang::exceptions::IndexOutOfBoundsException(
                    __FILE__, __LINE__,
                    "List::listIterator - Index greater than size() or negative");
            }

            return new StlListIterator(&values, index);
        }
        virtual ListIterator<E>* listIterator(int index) const {

            if (index < 0 || index > this->size()) {
                throw decaf::lang::exceptions::IndexOutOfBoundsException(
                    __FILE__, __LINE__,
                    "List::listIterator - Index greater than size() or negative");
            }

            return new ConstStlListIterator(&values, index);
        }

        /**
         * {@inheritDoc}
         */
        virtual void clear() {
            values.clear();
        }

        /**
         * {@inheritDoc}
         */
        virtual bool isEmpty() const {
            return values.empty();
        }

        /**
         * {@inheritDoc}
         */
        virtual int size() const {
            return (int)values.size();
        }

        /**
         * {@inheritDoc}
         */
        virtual E get(int index) const {

            if( index < 0 || index >= this->size() ) {
                throw decaf::lang::exceptions::IndexOutOfBoundsException(
                    __FILE__, __LINE__,
                    "List::get - Index greater than size() or negative" );
            }

            // Advance from begin and return the value at that location.
            typename std::list<E>::const_iterator iter = this->values.begin();
            std::advance( iter, index );
            return *( iter );
        }

        /**
         * {@inheritDoc}
         */
        virtual E set(int index, const E& element) {

            if (index < 0 || index >= this->size()) {
                throw decaf::lang::exceptions::IndexOutOfBoundsException(
                    __FILE__, __LINE__,
                    "List::get - Index greater than size() or negative");
            }

            // Advance from begin and return the value at that location
            // after setting the value to the new value.
            typename std::list<E>::iterator iter = this->values.begin();
            std::advance(iter, index);
            E oldValue = *iter;
            *iter = element;

            return oldValue;
        }

        virtual void add(int index, const E& element) {

            if (index < 0 || index > this->size()) {
                throw decaf::lang::exceptions::IndexOutOfBoundsException(
                    __FILE__, __LINE__,
                    "List::add - Index greater than size()");
            }

            // Advance from begin and insert the value at that location
            typename std::list<E>::iterator iter = this->values.begin();
            std::advance(iter, index);
            this->values.insert(iter, element);
        }

        virtual bool add(const E& value) {
            values.insert(values.end(), value);
            return true;
        }

        virtual bool addAll(const Collection<E>& collection) {

            if (collection.isEmpty()) {
                return false;
            }

            std::vector<E> array = collection.toArray();
            typename std::vector<E>::const_iterator vecIter = array.begin();

            std::auto_ptr<ListIterator<E> > iter(this->listIterator((int) this->values.size()));

            while (vecIter != array.end()) {
                iter->add(*(vecIter++));
            }

            return true;
        }

        virtual bool addAll(int index, const Collection<E>& collection) {

            if (index < 0 || index > this->size()) {
                throw decaf::lang::exceptions::IndexOutOfBoundsException(
                    __FILE__, __LINE__,
                    "List::addAll - Index greater than size()");
            }

            if (collection.isEmpty()) {
                return false;
            }

            std::vector<E> array = collection.toArray();
            typename std::vector<E>::const_iterator vecIter = array.begin();

            std::auto_ptr<ListIterator<E> > iter(this->listIterator(index));

            while (vecIter != array.end()) {
                iter->add(*(vecIter++));
            }

            return true;
        }

        virtual bool remove(const E& value) {
            int origSize = this->size();
            this->values.remove(value);
            return origSize != this->size();
        }

        virtual E removeAt(int index) {

            if (index < 0 || index >= this->size()) {
                throw decaf::lang::exceptions::IndexOutOfBoundsException(
                    __FILE__, __LINE__,
                    "List::removeAt - Index greater than size() or negative");
            }

            // Advance from begin and insert the value at that location
            typename std::list<E>::iterator iter = this->values.begin();
            std::advance(iter, index);
            E oldValue = *iter;
            this->values.erase(iter);

            return oldValue;
        }

        virtual int indexOf(const E& value) const {

            typename std::list<E>::const_iterator iter;
            iter = std::find(values.begin(), values.end(), value);

            if (iter == values.end()) {
                return -1;
            }

            return (int) std::distance(values.begin(), iter);
        }

        virtual int lastIndexOf(const E& value) const {

            typename std::list<E>::const_reverse_iterator iter;
            iter = std::find(values.rbegin(), values.rend(), value);

            if (iter == values.rend()) {
                return -1;
            }

            // Now reverse the result to get the last index
            return (int) (this->size() - std::distance(values.rbegin(), iter) - 1);
        }

        virtual bool contains(const E& value) const {
            typename std::list<E>::const_iterator iter;
            iter = std::find(values.begin(), values.end(), value);
            return iter != values.end();
        }

    };

}}

#endif /*_DECAF_UTIL_STLLIST_H_*/
