/*
 * 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_HASHMAP_H_
#define _DECAF_UTIL_HASHMAP_H_

#include <decaf/util/Config.h>

#include <decaf/util/AbstractMap.h>
#include <decaf/util/AbstractSet.h>
#include <decaf/util/HashCode.h>
#include <decaf/util/ConcurrentModificationException.h>
#include <decaf/lang/exceptions/UnsupportedOperationException.h>
#include <decaf/lang/Pointer.h>
#include <decaf/lang/ArrayPointer.h>

namespace decaf {
namespace util {

    /**
     * Hash table based implementation of the Map interface. This implementation provides all
     * of the optional map operations, and permits null values and the null key.  This class
     * makes no guarantees as to the order of the map; in particular, it does not guarantee
     * that the order will remain constant over time.
     *
     * This implementation provides constant-time performance for the basic operations (get
     * and put), assuming the hash function disperses the elements properly among the buckets.
     * Iteration over collection views requires time proportional to the "capacity" of the
     * HashMap instance (the number of buckets) plus its size (the number of key-value mappings).
     * Thus, it's very important not to set the initial capacity too high (or the load factor too
     * low) if iteration performance is important.
     *
     * An instance of HashMap has two parameters that affect its performance: initial capacity
     * and load factor. The capacity is the number of buckets in the hash table, and the initial
     * capacity is simply the capacity at the time the hash table is created. The load factor is
     * a measure of how full the hash table is allowed to get before its capacity is automatically
     * increased. When the number of entries in the hash table exceeds the product of the load
     * factor and the current capacity, the hash table is rehashed (that is, internal data
     * structures are rebuilt) so that the hash table has approximately twice the number of buckets.
     *
     * As a general rule, the default load factor (.75) offers a good tradeoff between time and
     * space costs. Higher values decrease the space overhead but increase the lookup cost
     * (reflected in most of the operations of the HashMap class, including get and put). The
     * expected number of entries in the map and its load factor should be taken into account
     * when setting its initial capacity, so as to minimize the number of rehash operations. If
     * the initial capacity is greater than the maximum number of entries divided by the load
     * factor, no rehash operations will ever occur.
     *
     * If many mappings are to be stored in a HashMap instance, creating it with a sufficiently
     * large capacity will allow the mappings to be stored more efficiently than letting it
     * perform automatic rehashing as needed to grow the table.
     *
     * Note that this implementation is not synchronized. If multiple threads access a hash map
     * concurrently, and at least one of the threads modifies the map structurally, it must be
     * synchronized externally. (A structural modification is any operation that adds or deletes
     * one or more mappings; merely changing the value associated with a key that an instance
     * already contains is not a structural modification.) This is typically accomplished by
     * synchronizing on some object that naturally encapsulates the map. If no such object
     * exists, the map should be "wrapped" using the Collections::synchronizedMap method.
     * This is best done at creation time, to prevent accidental unsynchronized access to the map:
     *
     *   Map<K, V>* map = Collections::synchronizedMap(new HashMap<K, V>());
     *
     * The iterators returned by all of this class's "collection view methods" are fail-fast:
     * if the map is structurally modified at any time after the iterator is created, in any
     * way except through the iterator's own remove method, the iterator will throw a
     * ConcurrentModificationException. Thus, in the face of concurrent modification, the
     * iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic
     * behavior at an undetermined time in the future.
     *
     * Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally
     * speaking, impossible to make any hard guarantees in the presence of unsynchronized
     * concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a
     * best-effort basis. Therefore, it would be wrong to write a program that depended on this
     * exception for its correctness: the fail-fast behavior of iterators should be used only
     * to detect bugs.
     *
     * @since 1.0
     */
    template<typename K, typename V, typename HASHCODE = HashCode<K> >
    class HashMap : public AbstractMap<K, V> {
    protected:

        class HashMapEntry : public MapEntry<K, V> {
        private:

            HashMapEntry(const HashMapEntry&);
            HashMapEntry& operator= (const HashMapEntry&);

        public:

            int origKeyHash;

            HashMapEntry* next;

            HashMapEntry(const K& key, const V& value, int hash) : MapEntry<K, V>(), origKeyHash(hash), next(NULL) {
                this->setKey(key);
                this->setValue(value);
                this->origKeyHash = hash;
            }

            HashMapEntry(const K& key, const V& value) : MapEntry<K, V>(key, value), origKeyHash(0), next(NULL){
                this->origKeyHash = HASHCODE()(key);
            }

        };

    private:

        class AbstractMapIterator {
        protected:

            mutable int position;
            int expectedModCount;
            HashMapEntry* futureEntry;
            HashMapEntry* currentEntry;
            HashMapEntry* prevEntry;

            HashMap* associatedMap;

        private:

            AbstractMapIterator(const AbstractMapIterator&);
            AbstractMapIterator& operator= (const AbstractMapIterator&);

        public:

            AbstractMapIterator(HashMap* parent) : position(0),
                                                   expectedModCount(parent->modCount),
                                                   futureEntry(NULL),
                                                   currentEntry(NULL),
                                                   prevEntry(NULL),
                                                   associatedMap(parent) {
            }

            virtual ~AbstractMapIterator() {}

            virtual bool checkHasNext() const {
                if (futureEntry != NULL) {
                    return true;
                }
                while (position < associatedMap->elementData.length()) {
                    if (associatedMap->elementData[position] == NULL) {
                        position++;
                    } else {
                        return true;
                    }
                }
                return false;
            }

            void checkConcurrentMod() const {
                if (expectedModCount != associatedMap->modCount) {
                    throw ConcurrentModificationException(
                        __FILE__, __LINE__, "HashMap modified outside this iterator");
                }
            }

            void makeNext() {
                checkConcurrentMod();

                if (!checkHasNext()) {
                    throw NoSuchElementException(__FILE__, __LINE__, "No next element");
                }

                if (futureEntry == NULL) {
                    currentEntry = associatedMap->elementData[position++];
                    futureEntry = currentEntry->next;
                    prevEntry = NULL;
                } else {
                    if (currentEntry != NULL){
                        prevEntry = currentEntry;
                    }
                    currentEntry = futureEntry;
                    futureEntry = futureEntry->next;
                }
            }

            virtual void doRemove() {

                checkConcurrentMod();

                if (currentEntry == NULL) {
                    throw decaf::lang::exceptions::IllegalStateException(
                        __FILE__, __LINE__, "Remove called before call to next()");
                }

                if (prevEntry == NULL){
                    int index = currentEntry->origKeyHash & (associatedMap->elementData.length() - 1);
                    associatedMap->elementData[index] = associatedMap->elementData[index]->next;
                } else {
                    prevEntry->next = currentEntry->next;
                }

                delete currentEntry;
                currentEntry = NULL;

                expectedModCount++;
                associatedMap->modCount++;
                associatedMap->elementCount--;
            }
        };

        class EntryIterator : public Iterator< MapEntry<K,V> >, public AbstractMapIterator {
        private:

            EntryIterator(const EntryIterator&);
            EntryIterator& operator= (const EntryIterator&);

        public:

            EntryIterator(HashMap* parent) : AbstractMapIterator(parent) {
            }

            virtual ~EntryIterator() {}

            virtual bool hasNext() const {
                return this->checkHasNext();
            }

            virtual MapEntry<K, V> next() {
                this->makeNext();
                return *(this->currentEntry);
            }

            virtual void remove() {
                this->doRemove();
            }
        };

        class KeyIterator : public Iterator<K>, public AbstractMapIterator {
        private:

            KeyIterator(const KeyIterator&);
            KeyIterator& operator= (const KeyIterator&);

        public:

            KeyIterator(HashMap* parent) : AbstractMapIterator(parent) {
            }

            virtual ~KeyIterator() {}

            virtual bool hasNext() const {
                return this->checkHasNext();
            }

            virtual K next() {
                this->makeNext();
                return this->currentEntry->getKey();
            }

            virtual void remove() {
                this->doRemove();
            }
        };

        class ValueIterator : public Iterator<V>, public AbstractMapIterator {
        private:

            ValueIterator(const ValueIterator&);
            ValueIterator& operator= (const ValueIterator&);

        public:

            ValueIterator(HashMap* parent) : AbstractMapIterator(parent) {
            }

            virtual ~ValueIterator() {}

            virtual bool hasNext() const {
                return this->checkHasNext();
            }

            virtual V next() {
                this->makeNext();
                return this->currentEntry->getValue();
            }

            virtual void remove() {
                this->doRemove();
            }
        };

    private:

        class ConstAbstractMapIterator {
        protected:

            mutable int position;
            int expectedModCount;
            const HashMapEntry* futureEntry;
            const HashMapEntry* currentEntry;
            const HashMapEntry* prevEntry;

            const HashMap* associatedMap;

        private:

            ConstAbstractMapIterator(const ConstAbstractMapIterator&);
            ConstAbstractMapIterator& operator= (const ConstAbstractMapIterator&);

        public:

            ConstAbstractMapIterator(const HashMap* parent) : position(0),
                                                              expectedModCount(parent->modCount),
                                                              futureEntry(NULL),
                                                              currentEntry(NULL),
                                                              prevEntry(NULL),
                                                              associatedMap(parent) {
            }

            virtual ~ConstAbstractMapIterator() {}

            virtual bool checkHasNext() const {
                if (futureEntry != NULL) {
                    return true;
                }
                while (position < associatedMap->elementData.length()) {
                    if (associatedMap->elementData[position] == NULL) {
                        position++;
                    } else {
                        return true;
                    }
                }
                return false;
            }

            void checkConcurrentMod() const {
                if (expectedModCount != associatedMap->modCount) {
                    throw ConcurrentModificationException(
                        __FILE__, __LINE__, "HashMap modified outside this iterator");
                }
            }

            void makeNext() {
                checkConcurrentMod();

                if (!checkHasNext()) {
                    throw NoSuchElementException(__FILE__, __LINE__, "No next element");
                }

                if (futureEntry == NULL) {
                    currentEntry = associatedMap->elementData[position++];
                    futureEntry = currentEntry->next;
                    prevEntry = NULL;
                } else {
                    if (currentEntry != NULL){
                        prevEntry = currentEntry;
                    }
                    currentEntry = futureEntry;
                    futureEntry = futureEntry->next;
                }
            }
        };

        class ConstEntryIterator : public Iterator< MapEntry<K,V> >, public ConstAbstractMapIterator {
        private:

            ConstEntryIterator(const ConstEntryIterator&);
            ConstEntryIterator& operator= (const ConstEntryIterator&);

        public:

            ConstEntryIterator(const HashMap* parent) : ConstAbstractMapIterator(parent) {
            }

            virtual ~ConstEntryIterator() {}

            virtual bool hasNext() const {
                return this->checkHasNext();
            }

            virtual MapEntry<K, V> next() {
                this->makeNext();
                return *(this->currentEntry);
            }

            virtual void remove() {
                throw lang::exceptions::UnsupportedOperationException(
                    __FILE__, __LINE__, "Cannot write to a const Iterator.");
            }
        };

        class ConstKeyIterator : public Iterator<K>, public ConstAbstractMapIterator {
        private:

            ConstKeyIterator(const ConstKeyIterator&);
            ConstKeyIterator& operator= (const ConstKeyIterator&);

        public:

            ConstKeyIterator(const HashMap* parent) : ConstAbstractMapIterator(parent) {
            }

            virtual ~ConstKeyIterator() {}

            virtual bool hasNext() const {
                return this->checkHasNext();
            }

            virtual K next() {
                this->makeNext();
                return this->currentEntry->getKey();
            }

            virtual void remove() {
                throw lang::exceptions::UnsupportedOperationException(
                    __FILE__, __LINE__, "Cannot write to a const Iterator.");
            }
        };

        class ConstValueIterator : public Iterator<V>, public ConstAbstractMapIterator {
        private:

            ConstValueIterator(const ConstValueIterator&);
            ConstValueIterator& operator= (const ConstValueIterator&);

        public:

            ConstValueIterator(const HashMap* parent) : ConstAbstractMapIterator(parent) {
            }

            virtual ~ConstValueIterator() {}

            virtual bool hasNext() const {
                return this->checkHasNext();
            }

            virtual V next() {
                this->makeNext();
                return this->currentEntry->getValue();
            }

            virtual void remove() {
                throw lang::exceptions::UnsupportedOperationException(
                    __FILE__, __LINE__, "Cannot write to a const Iterator.");
            }
        };

    protected:

        // Special Set implementation that is backed by this HashMap
        class HashMapEntrySet : public AbstractSet< MapEntry<K, V> > {
        private:

            HashMap* associatedMap;

        private:

            HashMapEntrySet(const HashMapEntrySet&);
            HashMapEntrySet& operator= (const HashMapEntrySet&);

        public:

            HashMapEntrySet(HashMap* parent) : AbstractSet< MapEntry<K,V> >(), associatedMap(parent) {
            }

            virtual ~HashMapEntrySet() {}

            virtual int size() const {
                return associatedMap->elementCount;
            }

            virtual void clear() {
                associatedMap->clear();
            }

            virtual bool remove(const MapEntry<K,V>& entry) {
                HashMapEntry* result = associatedMap->getEntry(entry.getKey());
                if (result != NULL && entry.getValue() == result->getValue()) {
                    associatedMap->removeEntry(result);
                    return true;
                }

                return false;
            }

            virtual bool contains(const MapEntry<K,V>& entry) const {
                HashMapEntry* result = associatedMap->getEntry(entry.getKey());
                if (result != NULL && entry.getValue() == result->getValue()) {
                    return true;
                }
                return false;
            }

            virtual Iterator< MapEntry<K, V> >* iterator() {
                return new EntryIterator(associatedMap);
            }

            virtual Iterator< MapEntry<K, V> >* iterator() const {
                return new ConstEntryIterator(associatedMap);
            }
        };

        // Special Set implementation that is backed by this HashMap
        class ConstHashMapEntrySet : public AbstractSet< MapEntry<K, V> > {
        private:

            const HashMap* associatedMap;

        private:

            ConstHashMapEntrySet(const ConstHashMapEntrySet&);
            ConstHashMapEntrySet& operator= (const ConstHashMapEntrySet&);

        public:

            ConstHashMapEntrySet(const HashMap* parent) : AbstractSet< MapEntry<K,V> >(), associatedMap(parent) {
            }

            virtual ~ConstHashMapEntrySet() {}

            virtual int size() const {
                return associatedMap->elementCount;
            }

            virtual void clear() {
                throw decaf::lang::exceptions::UnsupportedOperationException(
                        __FILE__, __LINE__, "Can't clear a const collection");
            }

            virtual bool remove(const MapEntry<K,V>& entry DECAF_UNUSED) {
                throw decaf::lang::exceptions::UnsupportedOperationException(
                        __FILE__, __LINE__, "Can't remove from const collection");
            }

            virtual bool contains(const MapEntry<K,V>& entry) const {
                HashMapEntry* result = associatedMap->getEntry(entry.getKey());
                if (result != NULL && entry.getValue() == result->getValue()) {
                    return true;
                }
                return false;
            }

            virtual Iterator< MapEntry<K, V> >* iterator() {
                throw decaf::lang::exceptions::UnsupportedOperationException(
                        __FILE__, __LINE__, "Can't return a non-const iterator for a const collection");
            }

            virtual Iterator< MapEntry<K, V> >* iterator() const {
                return new ConstEntryIterator(associatedMap);
            }
        };

    protected:

        class HashMapKeySet : public AbstractSet<K> {
        private:

            HashMap* associatedMap;

        private:

            HashMapKeySet(const HashMapKeySet&);
            HashMapKeySet& operator= (const HashMapKeySet&);

        public:

            HashMapKeySet(HashMap* parent) : AbstractSet<K>(), associatedMap(parent) {
            }

            virtual ~HashMapKeySet() {}

            virtual bool contains(const K& key) const {
                return this->associatedMap->containsKey(key);
            }

            virtual int size() const {
                return this->associatedMap->size();
            }

            virtual void clear() {
                this->associatedMap->clear();
            }

            virtual bool remove(const K& key) {
                HashMapEntry* entry = this->associatedMap->removeEntry(key);
                if (entry != NULL) {
                    delete entry;
                    return true;
                }
                return false;
            }

            virtual Iterator<K>* iterator() {
                return new KeyIterator(this->associatedMap);
            }

            virtual Iterator<K>* iterator() const {
                return new ConstKeyIterator(this->associatedMap);
            }
        };

        class ConstHashMapKeySet : public AbstractSet<K> {
        private:

            const HashMap* associatedMap;

        private:

            ConstHashMapKeySet(const ConstHashMapKeySet&);
            ConstHashMapKeySet& operator= (const ConstHashMapKeySet&);

        public:

            ConstHashMapKeySet(const HashMap* parent) : AbstractSet<K>(), associatedMap(parent) {
            }

            virtual ~ConstHashMapKeySet() {}

            virtual bool contains(const K& key) const {
                return this->associatedMap->containsKey(key);
            }

            virtual int size() const {
                return this->associatedMap->size();
            }

            virtual void clear() {
                throw decaf::lang::exceptions::UnsupportedOperationException(
                        __FILE__, __LINE__, "Can't modify a const collection");
            }

            virtual bool remove(const K& key DECAF_UNUSED) {
                throw decaf::lang::exceptions::UnsupportedOperationException(
                        __FILE__, __LINE__, "Can't modify a const collection");
            }

            virtual Iterator<K>* iterator() {
                throw decaf::lang::exceptions::UnsupportedOperationException(
                        __FILE__, __LINE__, "Can't return a non-const iterator for a const collection");
            }

            virtual Iterator<K>* iterator() const {
                return new ConstKeyIterator(this->associatedMap);
            }
        };

    protected:

        class HashMapValueCollection : public AbstractCollection<V> {
        private:

            HashMap* associatedMap;

        private:

            HashMapValueCollection(const HashMapValueCollection&);
            HashMapValueCollection& operator= (const HashMapValueCollection&);

        public:

            HashMapValueCollection(HashMap* parent) : AbstractCollection<V>(), associatedMap(parent) {
            }

            virtual ~HashMapValueCollection() {}

            virtual bool contains(const V& value) const {
                return this->associatedMap->containsValue(value);
            }

            virtual int size() const {
                return this->associatedMap->size();
            }

            virtual void clear() {
                this->associatedMap->clear();
            }

            virtual Iterator<V>* iterator() {
                return new ValueIterator(this->associatedMap);
            }

            virtual Iterator<V>* iterator() const {
                return new ConstValueIterator(this->associatedMap);
            }
        };

        class ConstHashMapValueCollection : public AbstractCollection<V> {
        private:

            const HashMap* associatedMap;

        private:

            ConstHashMapValueCollection(const ConstHashMapValueCollection&);
            ConstHashMapValueCollection& operator= (const ConstHashMapValueCollection&);

        public:

            ConstHashMapValueCollection(const HashMap* parent) : AbstractCollection<V>(), associatedMap(parent) {
            }

            virtual ~ConstHashMapValueCollection() {}

            virtual bool contains(const V& value) const {
                return this->associatedMap->containsValue(value);
            }

            virtual int size() const {
                return this->associatedMap->size();
            }

            virtual void clear() {
                throw decaf::lang::exceptions::UnsupportedOperationException(
                        __FILE__, __LINE__, "Can't modify a const collection");
            }

            virtual Iterator<V>* iterator() {
                throw decaf::lang::exceptions::UnsupportedOperationException(
                        __FILE__, __LINE__, "Can't return a non-const iterator for a const collection");
            }

            virtual Iterator<V>* iterator() const {
                return new ConstValueIterator(this->associatedMap);
            }
        };

    protected:

        /**
         * The Hash Code generator for this map's keys.
         */
        HASHCODE hashFunc;

        /*
         * Actual count of entries
         */
        int elementCount;

        /*
         * The internal data structure to hold Entries, Array of MapEntry pointers.
         */
        decaf::lang::ArrayPointer<HashMapEntry*> elementData;

        /*
         * modification count, to keep track of structural modifications between the
         * HashMap and the iterator
         */
        int modCount;

        /*
         * maximum ratio of (stored elements)/(storage size) which does not lead to rehash
         */
        float loadFactor;

        /*
         * maximum number of elements that can be put in this map before having to rehash
         */
        int threshold;

        // Cached values that are only initialized once a request for them is made.
        decaf::lang::Pointer<HashMapEntrySet> cachedEntrySet;
        decaf::lang::Pointer<HashMapKeySet> cachedKeySet;
        decaf::lang::Pointer<HashMapValueCollection> cachedValueCollection;

        // Cached values that are only initialized once a request for them is made.
        mutable decaf::lang::Pointer<ConstHashMapEntrySet> cachedConstEntrySet;
        mutable decaf::lang::Pointer<ConstHashMapKeySet> cachedConstKeySet;
        mutable decaf::lang::Pointer<ConstHashMapValueCollection> cachedConstValueCollection;

    private:

        void computeThreshold() {
            threshold = (int) ((float) elementData.length() * loadFactor);
        }

        static int calculateCapacity(int x) {
            if (x >= 1 << 30) {
                return 1 << 30;
            }

            if (x == 0) {
                return 16;
            }
            x = x - 1;
            x |= x >> 1;
            x |= x >> 2;
            x |= x >> 4;
            x |= x >> 8;
            x |= x >> 16;
            return x + 1;
        }

    public:

        /**
         * Creates a new empty HashMap with default configuration settings.
         */
        HashMap() : AbstractMap<K,V>(), hashFunc(), elementCount(0), elementData(),
                    modCount(0), loadFactor(0.75), threshold(0),
                    cachedEntrySet(), cachedKeySet(), cachedValueCollection(),
                    cachedConstEntrySet(), cachedConstKeySet(), cachedConstValueCollection() {
            int capacity = calculateCapacity(12);
            elementCount = 0;
            elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
            computeThreshold();
        }

        /**
         * Constructs a new HashMap instance with the specified capacity.
         *
         * @param capacity
         * 		The initial capacity of this hash map.
         *
         * @throws IllegalArgumentException when the capacity is less than zero.
         */
        HashMap(int capacity) : AbstractMap<K,V>(), hashFunc(), elementCount(0),
                                elementData(), modCount(0), loadFactor(0.75), threshold(0),
                                cachedEntrySet(), cachedKeySet(), cachedValueCollection(),
                                cachedConstEntrySet(), cachedConstKeySet(), cachedConstValueCollection() {
            if (capacity >= 0) {
                capacity = calculateCapacity(capacity);
                elementCount = 0;
                elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
                computeThreshold();
            } else {
                throw decaf::lang::exceptions::IllegalArgumentException(
                        __FILE__, __LINE__, "Invalid capacity configuration");
            }
        }

        /**
         * Constructs a new HashMap instance with the specified capacity.
         *
         * @param capacity
         * 		The initial capacity of this hash map.
         * @param loadFactor
         * 		The load factor to use for this hash map.
         *
         * @throws IllegalArgumentException when the capacity is less than zero.
         */
        HashMap(int capacity, float loadFactor) : AbstractMap<K,V>(), hashFunc(), elementCount(0),
                                                  elementData(), modCount(0), loadFactor(0.75), threshold(0),
                                                  cachedEntrySet(), cachedKeySet(), cachedValueCollection(),
                                                  cachedConstEntrySet(), cachedConstKeySet(), cachedConstValueCollection() {
            if (capacity >= 0 && loadFactor > 0) {
                capacity = calculateCapacity(capacity);
                elementCount = 0;
                elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
                this->loadFactor = loadFactor;
                computeThreshold();
            } else {
                throw decaf::lang::exceptions::IllegalArgumentException(
                        __FILE__, __LINE__, "Invalid configuration");
            }
        }

        /**
         * Creates a new HashMap with default configuration settings and fills it with the contents
         * of the given source Map instance.
         *
         * @param map
         *      The Map instance whose elements are copied into this HashMap instance.
         */
        HashMap(const HashMap<K,V>& map) : AbstractMap<K,V>(), hashFunc(), elementCount(0), elementData(),
                                           modCount(0), loadFactor(0.75), threshold(0),
                                           cachedEntrySet(), cachedKeySet(), cachedValueCollection(),
                                           cachedConstEntrySet(), cachedConstKeySet(), cachedConstValueCollection() {
            int capacity = calculateCapacity(map.size());
            elementCount = 0;
            elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
            computeThreshold();
            putAll(map);
        }

        /**
         * Creates a new HashMap with default configuration settings and fills it with the contents
         * of the given source Map instance.
         *
         * @param map
         * 		The Map instance whose elements are copied into this HashMap instance.
         */
        HashMap(const Map<K,V>& map) : AbstractMap<K,V>(), hashFunc(), elementCount(0), elementData(),
                                       modCount(0), loadFactor(0.75), threshold(0),
                                       cachedEntrySet(), cachedKeySet(), cachedValueCollection(),
                                       cachedConstEntrySet(), cachedConstKeySet(), cachedConstValueCollection() {
            int capacity = calculateCapacity(map.size());
            elementCount = 0;
            elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
            computeThreshold();
            putAll(map);
        }

        virtual ~HashMap() {
            for (int i = 0; i < elementData.length(); i++) {
                HashMapEntry* entry = elementData[i];
                while (entry != NULL) {
                    HashMapEntry* temp = entry;
                    entry = entry->next;
                    delete temp;
                }
            }
        }

    public:

        HashMap<K, V>& operator= (const Map<K, V>& other) {
            this->copy(other);
            return *this;
        }

        HashMap<K, V>& operator= (const HashMap<K, V>& other) {
            this->copy(other);
            return *this;
        }

        bool operator==(const Map<K, V>& other) const {
            return this->equals(other);
        }

        bool operator!=(const Map<K, V>& other) const {
            return !this->equals(other);
        }

    public:

        virtual void clear() {
            if (elementCount > 0) {
                elementCount = 0;
                for (int i = 0; i < elementData.length(); ++i) {
                    HashMapEntry* entry = elementData[i];
                    elementData[i] = NULL;
                    while (entry != NULL) {
                        HashMapEntry* temp = entry;
                        entry = entry->next;
                        delete temp;
                    }
                }
                modCount++;
            }
        }

        virtual bool isEmpty() const {
            return elementCount == 0;
        }

        virtual int size() const {
            return elementCount;
        }

        virtual bool containsKey(const K& key) const {
            const HashMapEntry* entry = getEntry(key);
            return entry != NULL;
        }

        virtual bool containsValue(const V& value) const {
            for (int i = 0; i < elementData.length(); i++) {
                const HashMapEntry* entry = elementData[i];
                while (entry != NULL) {
                    if (value == entry->getValue()) {
                        return true;
                    }
                    entry = entry->next;
                }
            }
            return false;
        }

        virtual V& get(const K& key) {
            HashMapEntry* entry = getEntry(key);
            if (entry != NULL) {
                return entry->getValue();
            }

            throw NoSuchElementException(
                    __FILE__, __LINE__, "The specified key is not present in the Map");
        }

        virtual const V& get(const K& key) const {
            const HashMapEntry* entry = getEntry(key);
            if (entry != NULL) {
                return entry->getValue();
            }

            throw NoSuchElementException(
                    __FILE__, __LINE__, "The specified key is not present in the Map");
        }

        virtual bool put(const K& key, const V& value) {
            return this->putImpl(key, value);
        }

        virtual bool put(const K& key, const V& value, V& oldValue) {
            return this->putImpl(key, value, oldValue);
        }

        virtual void putAll(const Map<K, V>& map) {
            if (!map.isEmpty()) {
                putAllImpl(map);
            }
        }

        virtual V remove(const K& key) {
            HashMapEntry* entry = removeEntry(key);
            if (entry != NULL) {
                V oldValue = entry->getValue();
                delete entry;
                return oldValue;
            }

            throw NoSuchElementException(
                __FILE__, __LINE__, "Specified key not present in the Map.");
        }

        virtual Set< MapEntry<K,V> >& entrySet() {
            if (this->cachedEntrySet == NULL) {
                this->cachedEntrySet.reset(new HashMapEntrySet(this));
            }
            return *(this->cachedEntrySet);
        }

        virtual const Set< MapEntry<K,V> >& entrySet() const {
            if (this->cachedConstEntrySet == NULL) {
                this->cachedConstEntrySet.reset(new ConstHashMapEntrySet(this));
            }
            return *(this->cachedConstEntrySet);
        }

        virtual Set<K>& keySet() {
            if (this->cachedKeySet == NULL) {
                this->cachedKeySet.reset(new HashMapKeySet(this));
            }
            return *(this->cachedKeySet);
        }

        virtual const Set<K>& keySet() const {
            if (this->cachedConstKeySet == NULL) {
                this->cachedConstKeySet.reset(new ConstHashMapKeySet(this));
            }
            return *(this->cachedConstKeySet);
        }

        virtual Collection<V>& values() {
            if (this->cachedValueCollection == NULL) {
                this->cachedValueCollection.reset(new HashMapValueCollection(this));
            }
            return *(this->cachedValueCollection);
        }

        virtual const Collection<V>& values() const {
            if (this->cachedConstValueCollection == NULL) {
                this->cachedConstValueCollection.reset(new ConstHashMapValueCollection(this));
            }
            return *(this->cachedConstValueCollection);
        }

        virtual bool equals(const Map<K, V>& source) const {

            if (this == &source) {
                return true;
            }

            if (size() != source.size()) {
                return false;
            }

            try {
                decaf::lang::Pointer<Iterator<MapEntry<K, V> > > iter(entrySet().iterator());
                while (iter->hasNext() ) {
                    MapEntry<K, V> entry = iter->next();
                    K key = entry.getKey();
                    V mine = entry.getValue();

                    if (!source.containsKey(key)) {
                        return false;
                    }

                    if (source.get(key) != mine) {
                        return false;
                    }
                }
            } catch (decaf::lang::exceptions::NullPointerException& ignored) {
                return false;
            } catch (decaf::lang::exceptions::ClassCastException& ignored) {
                return false;
            }
            return true;
        }

        virtual void copy(const Map<K, V>& source) {
            int capacity = calculateCapacity(source.size());
            this->clear();
            if (capacity > elementData.length()) {
                elementData = decaf::lang::ArrayPointer<HashMapEntry*>(capacity);
            }
            computeThreshold();
            putAll(source);
        }

        virtual std::string toString() const {
            return "HashMap";
        }

    protected:

        virtual HashMapEntry* getEntry(const K& key) const {
            HashMapEntry* result = NULL;

            int hash = hashFunc(key);
            int index = hash & (elementData.length() - 1);
            result = findKeyEntry(key, index, hash);

            return result;
        }

        virtual bool putImpl(const K& key, const V& value) {
            V oldValue;
            return putImpl(key, value, oldValue);
        }

        virtual bool putImpl(const K& key, const V& value, V& oldValue) {
            bool replaced = true;
            HashMapEntry* entry = NULL;

            int hash = hashFunc(key);
            int index = hash & (elementData.length() - 1);

            entry = findKeyEntry(key, index, hash);

            if (entry == NULL) {
                modCount++;
                entry = createHashedEntry(key, index, hash);
                if (++elementCount > threshold) {
                    rehash();
                }
                replaced = false;
            } else {
                oldValue = entry->getValue();
            }

            entry->setValue(value);

            return replaced;
        }

        virtual HashMapEntry* createEntry(const K& key, int index, const V& value) {
            HashMapEntry* entry = new HashMapEntry(key, value);
            entry->next = elementData[index];
            elementData[index] = entry;
            return entry;
        }

        virtual HashMapEntry* createHashedEntry(const K& key, int index, int hash) {
            HashMapEntry* entry = new HashMapEntry(key, V(), hash);
            entry->next = elementData[index];
            elementData[index] = entry;
            return entry;
        }

    protected:

        void putAllImpl(const Map<K, V>& map) {
            int capacity = elementCount + map.size();
            if (capacity > threshold) {
                rehash(capacity);
            }

            decaf::lang::Pointer<Iterator< MapEntry<K,V> > > iterator(map.entrySet().iterator());
            while (iterator->hasNext()) {
                MapEntry<K, V> entry = iterator->next();
                this->putImpl(entry.getKey(), entry.getValue());
            }
        }

        HashMapEntry* findKeyEntry(const K& key, int index, int keyHash) const {
            HashMapEntry* entry = elementData[index];
            while (entry != NULL && (entry->origKeyHash != keyHash || !(key == entry->getKey()))) {
                entry = entry->next;
            }
            return entry;
        }

        void rehash(int capacity) {
            int length = calculateCapacity((capacity == 0 ? 1 : capacity << 1));

            decaf::lang::ArrayPointer<HashMapEntry*> newData(length);
            for (int i = 0; i < elementData.length(); i++) {
                HashMapEntry* entry = elementData[i];
                elementData[i] = NULL;
                while (entry != NULL) {
                    int index = entry->origKeyHash & (length - 1);
                    HashMapEntry* next = entry->next;
                    entry->next = newData[index];
                    newData[index] = entry;
                    entry = next;
                }
            }
            elementData = newData;
            computeThreshold();
        }

        void rehash() {
            rehash(elementData.length());
        }

        // Removes the given entry from the map and deletes it
        void removeEntry(HashMapEntry* entry) {
            int index = entry->origKeyHash & (elementData.length() - 1);
            HashMapEntry* current = elementData[index];
            if (current == entry) {
                elementData[index] = entry->next;
            } else {
                while (current->next != entry) {
                    current = current->next;
                }
                current->next = entry->next;
            }
            delete entry;
            modCount++;
            elementCount--;
        }

        // Removes but doesn't delete the entry in the map with the given key.
        HashMapEntry* removeEntry(const K& key) {

            int index = 0;
            HashMapEntry* current = NULL;
            HashMapEntry* last = NULL;

            int hash = hashFunc(key);
            index = hash & (elementData.length() - 1);
            current = elementData[index];
            while (current != NULL && !(current->origKeyHash == hash && key == current->getKey())) {
                last = current;
                current = current->next;
            }

            if (current == NULL) {
                return NULL;
            }

            if (last == NULL) {
                elementData[index] = current->next;
            } else {
                last->next = current->next;
            }

            modCount++;
            elementCount--;
            return current;
        }

    };

}}

#endif /* _DECAF_UTIL_HASHMAP_H_ */
