/*
 * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <wtf/Vector.h>

namespace WebCore {

WEBCORE_EXPORT void reportExtraMemoryAllocatedForCollectionIndexCache(size_t);

template <class Collection, class Iterator>
class CollectionIndexCache {
public:
    CollectionIndexCache();

    typedef typename std::iterator_traits<Iterator>::value_type NodeType;

    unsigned nodeCount(const Collection&);
    NodeType* nodeAt(const Collection&, unsigned index);

    bool hasValidCache() const { return m_current || m_nodeCountValid || m_listValid; }
    void invalidate();
    size_t memoryCost()
    {
        // memoryCost() may be invoked concurrently from a GC thread, and we need to be careful
        // about what data we access here and how. Accessing m_cachedList.capacity() is safe
        // because it doesn't involve any pointer chasing.
        return m_cachedList.capacity() * sizeof(NodeType*);
    }

private:
    unsigned computeNodeCountUpdatingListCache(const Collection&);
    NodeType* traverseBackwardTo(const Collection&, unsigned);
    NodeType* traverseForwardTo(const Collection&, unsigned);

    Iterator m_current { };
    unsigned m_currentIndex { 0 };
    unsigned m_nodeCount { 0 };
    Vector<NodeType*> m_cachedList;
    bool m_nodeCountValid : 1;
    bool m_listValid : 1;
};

template<class Collection, class Iterator> CollectionIndexCache<Collection, Iterator>::CollectionIndexCache()
    : m_nodeCountValid(false)
    , m_listValid(false)
{
}

template <class Collection, class Iterator>
inline unsigned CollectionIndexCache<Collection, Iterator>::nodeCount(const Collection& collection)
{
    if (!m_nodeCountValid) {
        if (!hasValidCache())
            collection.willValidateIndexCache();
        m_nodeCount = computeNodeCountUpdatingListCache(collection);
        m_nodeCountValid = true;
    }

    return m_nodeCount;
}

template <class Collection, class Iterator>
unsigned CollectionIndexCache<Collection, Iterator>::computeNodeCountUpdatingListCache(const Collection& collection)
{
    auto current = collection.collectionBegin();
    if (!current)
        return 0;

    unsigned oldCapacity = m_cachedList.capacity();
    while (current) {
        m_cachedList.append(&*current);
        unsigned traversed;
        collection.collectionTraverseForward(current, 1, traversed);
        ASSERT(traversed == (current ? 1 : 0));
    }
    m_listValid = true;

    if (unsigned capacityDifference = m_cachedList.capacity() - oldCapacity)
        reportExtraMemoryAllocatedForCollectionIndexCache(capacityDifference * sizeof(NodeType*));

    return m_cachedList.size();
}

template <class Collection, class Iterator>
inline typename CollectionIndexCache<Collection, Iterator>::NodeType* CollectionIndexCache<Collection, Iterator>::traverseBackwardTo(const Collection& collection, unsigned index)
{
    ASSERT(m_current);
    ASSERT(index < m_currentIndex);

    bool firstIsCloser = index < m_currentIndex - index;
    if (firstIsCloser || !collection.collectionCanTraverseBackward()) {
        m_current = collection.collectionBegin();
        m_currentIndex = 0;
        if (index)
            collection.collectionTraverseForward(m_current, index, m_currentIndex);
        ASSERT(m_current);
        return &*m_current;
    }

    collection.collectionTraverseBackward(m_current, m_currentIndex - index);
    m_currentIndex = index;

    ASSERT(m_current);
    return &*m_current;
}

template <class Collection, class Iterator>
inline typename CollectionIndexCache<Collection, Iterator>::NodeType* CollectionIndexCache<Collection, Iterator>::traverseForwardTo(const Collection& collection, unsigned index)
{
    ASSERT(m_current);
    ASSERT(index > m_currentIndex);
    ASSERT(!m_nodeCountValid || index < m_nodeCount);

    bool lastIsCloser = m_nodeCountValid && m_nodeCount - index < index - m_currentIndex;
    if (lastIsCloser && collection.collectionCanTraverseBackward()) {
        ASSERT(hasValidCache());
        m_current = collection.collectionLast();
        if (index < m_nodeCount - 1)
            collection.collectionTraverseBackward(m_current, m_nodeCount - index - 1);
        m_currentIndex = index;
        ASSERT(m_current);
        return &*m_current;
    }

    if (!hasValidCache())
        collection.willValidateIndexCache();

    unsigned traversedCount;
    collection.collectionTraverseForward(m_current, index - m_currentIndex, traversedCount);
    m_currentIndex = m_currentIndex + traversedCount;

    if (!m_current) {
        ASSERT(m_currentIndex < index);
        // Failed to find the index but at least we now know the size.
        m_nodeCount = m_currentIndex + 1;
        m_nodeCountValid = true;
        return nullptr;
    }
    ASSERT(hasValidCache());
    return &*m_current;
}

template <class Collection, class Iterator>
inline typename CollectionIndexCache<Collection, Iterator>::NodeType* CollectionIndexCache<Collection, Iterator>::nodeAt(const Collection& collection, unsigned index)
{
    if (m_nodeCountValid && index >= m_nodeCount)
        return nullptr;

    if (m_listValid)
        return m_cachedList[index];

    if (m_current) {
        if (index > m_currentIndex)
            return traverseForwardTo(collection, index);
        if (index < m_currentIndex)
            return traverseBackwardTo(collection, index);
        return &*m_current;
    }

    bool lastIsCloser = m_nodeCountValid && m_nodeCount - index < index;
    if (lastIsCloser && collection.collectionCanTraverseBackward()) {
        ASSERT(hasValidCache());
        m_current = collection.collectionLast();
        if (index < m_nodeCount - 1)
            collection.collectionTraverseBackward(m_current, m_nodeCount - index - 1);
        m_currentIndex = index;
        ASSERT(m_current);
        return &*m_current;
    }

    if (!hasValidCache())
        collection.willValidateIndexCache();

    m_current = collection.collectionBegin();
    m_currentIndex = 0;
    bool startIsEnd = !m_current;
    if (index && m_current) {
        collection.collectionTraverseForward(m_current, index, m_currentIndex);
        ASSERT(m_current || m_currentIndex < index);
    }
    if (!m_current) {
        // Failed to find the index but at least we now know the size.
        m_nodeCount = startIsEnd ? 0 : m_currentIndex + 1;
        m_nodeCountValid = true;
        return nullptr;
    }
    ASSERT(hasValidCache());
    return &*m_current;
}

template <class Collection, class Iterator>
void CollectionIndexCache<Collection, Iterator>::invalidate()
{
    m_current = { };
    m_nodeCountValid = false;
    m_listValid = false;
    m_cachedList.shrink(0);
}


}
