/*
 *  This file is part of the KDE libraries
 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
 *  Copyright (C) 2003 Apple Computer, Inc.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 *
 */

#ifndef KJS_LIST_H
#define KJS_LIST_H

#include "value.h"

namespace KJS {

    struct ListImpBase {
        int size;
        int refCount;
        int valueRefCount; // FIXME: Get rid of this.
    };
    
    class ListIterator;

    /**
     * @short Native list type.
     *
     * List is a native ECMAScript type. List values are only used for
     * intermediate results of expression evaluation and cannot be stored
     * as properties of objects.
     *
     * The list is explicitly shared. Note that while copyTail() returns a
     * copy of the list the referenced objects are still shared.
     */
    class List {
    public:
        List();
        ~List() { deref(); }

        List(const List &b) : _impBase(b._impBase) {
            ++_impBase->refCount; 
            ++_impBase->valueRefCount; 
        }
        List &operator=(const List &);

        /**
         * Append an object to the end of the list.
         *
         * @param val Pointer to object.
         */
        void append(JSValue *val);
        /**
         * Remove all elements from the list.
         */
        void clear();

        void reset() { deref(); ++(_impBase = empty()._impBase)->refCount; }

        /**
         * Make a copy of the list
         */
        List copy() const;

        /**
         * Copy all elements from the second list here
         */
        void copyFrom(const List& other);

        /**
         * Make a copy of the list, omitting the first element.
         */
        List copyTail() const;
    
        /**
         * @return true if the list is empty. false otherwise.
         */
        bool isEmpty() const { return _impBase->size == 0; }
        /**
         * @return the current size of the list.
         */
        int size() const { return _impBase->size; }
        /**
         * @return A KJS::ListIterator pointing to the first element.
         */
        ListIterator begin() const;
        /**
         * @return A KJS::ListIterator pointing to the last element.
         */
        ListIterator end() const;
        
        /**
         * Retrieve an element at an indexed position. If you want to iterate
         * trough the whole list using KJS::ListIterator will be faster.
         *
         * @param i List index.
         * @return Return the element at position i. KJS::Undefined if the
         * index is out of range.
         */
        JSValue *at(int i) const;
        /**
         * Equivalent to at.
         */
        JSValue *operator[](int i) const { return at(i); }
    
        /**
         * Returns a pointer to a static instance of an empty list. Useful if a
         * function has a KJS::List parameter.
         */
        static const List &empty();
        
        static void markProtectedLists();
    private:
        ListImpBase *_impBase;
        
        void deref() { --_impBase->valueRefCount; if (--_impBase->refCount == 0) release(); }

        void release();
        void markValues();
    };
  
    /**
     * @short Iterator for KJS::List objects.
     */
    class ListIterator {
    public:
        /**
         * Construct an iterator that points to the first element of the list.
         * @param l The list the iterator will operate on.
         */
        ListIterator(const List &l) : _list(&l), _i(0) { }
        ListIterator(const List &l, int index) : _list(&l), _i(index) { }
        /**
         * Dereference the iterator.
         * @return A pointer to the element the iterator operates on.
         */
        JSValue *operator->() const { return _list->at(_i); }
        JSValue *operator*() const { return _list->at(_i); }
        /**
         * Prefix increment operator.
         * @return The element after the increment.
         */
        JSValue *operator++() { return _list->at(++_i); }
        /**
         * Postfix increment operator.
         */
        JSValue *operator++(int) { return _list->at(_i++); }
        /**
         * Prefix decrement operator.
         */
        JSValue *operator--() { return _list->at(--_i); }
        /**
         * Postfix decrement operator.
         */
        JSValue *operator--(int) { return _list->at(_i--); }
        /**
         * Compare the iterator with another one.
         * @return True if the two iterators operate on the same list element.
         * False otherwise.
         */
        bool operator==(const ListIterator &it) const { return _i == it._i; }
        /**
         * Check for inequality with another iterator.
         * @return True if the two iterators operate on different list elements.
         */
        bool operator!=(const ListIterator &it) const { return _i != it._i; }

    private:
        const List *_list;
        int _i;
    };

    inline ListIterator List::begin() const { return ListIterator(*this); }
    inline ListIterator List::end() const { return ListIterator(*this, size()); }
 
} // namespace KJS

#endif // KJS_LIST_H
