/*
 * Copyright (C) 2012 Google 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
 * 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.
 */

#ifndef ImageDecodingStore_h
#define ImageDecodingStore_h

#include "SkSize.h"
#include "SkTypes.h"
#include "core/platform/graphics/chromium/DiscardablePixelRef.h"
#include "core/platform/graphics/chromium/ScaledImageFragment.h"
#include "core/platform/graphics/chromium/SkSizeHash.h"
#include "core/platform/image-decoders/ImageDecoder.h"

#include <wtf/DoublyLinkedList.h>
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/ThreadingPrimitives.h>
#include <wtf/Vector.h>

namespace WebCore {

class ImageFrameGenerator;
class SharedBuffer;

// FUNCTION
//
// ImageDecodingStore is a class used to manage image cache objects. There are two
// types of cache objects stored:
//
// 1. Image objects
//    Each image object belongs to one frame decoded and/or resampled from an image
//    file. The image object can be complete or partial. Complete means the image
//    is fully decoded and will not mutate in future decoding passes. It can have
//    multiple concurrent users. A partial image object has only one user.
//
// 2. Decoder objects
//    A decoder object contains an image decoder. This allows decoding to resume
//    from previous states. There can be one user per one decoder object at any
//    time.
//
// EXTERNAL OBJECTS
//
// ScaledImageFragment
//   A cached image object. Contains the bitmap and information about the bitmap
//   image.
//
// ImageDecoder
//   A decoder object. It is used to decode raw data into bitmap images.
//
// ImageFrameGenerator
//   This is a direct user of this cache. Responsible for generating bitmap images
//   using an ImageDecoder. It contains encoded image data and is used to represent
//   one image file. It is used to index image and decoder objects in the cache.
//
// LazyDecodingPixelRef
//   A read only user of this cache.
//
// THREAD SAFETY
//
// All public methods can be used on any thread.

class ImageDecodingStore {
public:
    static PassOwnPtr<ImageDecodingStore> create() { return adoptPtr(new ImageDecodingStore); }
    ~ImageDecodingStore();

    static ImageDecodingStore* instance();
    static void initializeOnce();
    static void shutdown();

    // Access a complete cached image object. A complete cached image object is
    // indexed by the origin (ImageFrameGenerator), scaled size and frame index
    // within the image file.
    // Return true if the cache object is found.
    // Return false if the cache object cannot be found or it is incomplete.
    bool lockCache(const ImageFrameGenerator*, const SkISize& scaledSize, size_t index, const ScaledImageFragment**);
    void unlockCache(const ImageFrameGenerator*, const ScaledImageFragment*);
    const ScaledImageFragment* insertAndLockCache(const ImageFrameGenerator*, PassOwnPtr<ScaledImageFragment>);

    // Access a cached decoder object. A decoder is indexed by origin (ImageFrameGenerator)
    // and scaled size. Return true if the cached object is found.
    bool lockDecoder(const ImageFrameGenerator*, const SkISize& scaledSize, ImageDecoder**);
    void unlockDecoder(const ImageFrameGenerator*, const ImageDecoder*);
    void insertDecoder(const ImageFrameGenerator*, PassOwnPtr<ImageDecoder>, bool isDiscardable);
    void removeDecoder(const ImageFrameGenerator*, const ImageDecoder*);

    // Locks the cache for safety, but does not attempt to lock the object we're checking for.
    bool isCached(const ImageFrameGenerator*, const SkISize& scaledSize, size_t index);

    // Remove all cache entries indexed by ImageFrameGenerator.
    void removeCacheIndexedByGenerator(const ImageFrameGenerator*);

    void clear();
    void setCacheLimitInBytes(size_t);
    size_t memoryUsageInBytes();
    unsigned cacheEntries();
    unsigned imageCacheEntries();
    unsigned decoderCacheEntries();

private:
    // Image cache entry is identified by:
    // 1. Pointer to ImageFrameGenerator.
    // 2. Size of the image.
    // 3. Frame index.
    // 4. Frame generation. Increments on each progressive decode.
    //
    // The use of generation ID is to allow multiple versions of an image frame
    // be stored in the cache. Each generation comes from a progressive decode.
    //
    // Decoder entries are identified by (1) and (2) only.
    typedef std::pair<const ImageFrameGenerator*, SkISize> DecoderCacheKey;
    typedef std::pair<size_t, size_t> IndexAndGeneration;
    typedef std::pair<DecoderCacheKey, IndexAndGeneration> ImageCacheKey;

    // Base class for all cache entries.
    class CacheEntry : public DoublyLinkedListNode<CacheEntry> {
        friend class WTF::DoublyLinkedListNode<CacheEntry>;
    public:
        enum CacheType {
            TypeImage,
            TypeDecoder,
        };

        CacheEntry(const ImageFrameGenerator* generator, int useCount, bool isDiscardable)
            : m_generator(generator)
            , m_useCount(useCount)
            , m_isDiscardable(isDiscardable)
            , m_prev(0)
            , m_next(0)
        {
        }

        virtual ~CacheEntry()
        {
            ASSERT(!m_useCount);
        }

        const ImageFrameGenerator* generator() const { return m_generator; }
        int useCount() const { return m_useCount; }
        void incrementUseCount() { ++m_useCount; }
        void decrementUseCount() { --m_useCount; ASSERT(m_useCount >= 0); }
        bool isDiscardable() const { return m_isDiscardable; }

        // FIXME: getSafeSize() returns size in bytes truncated to a 32-bits integer.
        //        Find a way to get the size in 64-bits.
        virtual size_t memoryUsageInBytes() const = 0;
        virtual CacheType type() const = 0;

    protected:
        const ImageFrameGenerator* m_generator;
        int m_useCount;
        bool m_isDiscardable;

    private:
        CacheEntry* m_prev;
        CacheEntry* m_next;
    };

    class ImageCacheEntry : public CacheEntry {
    public:
        static PassOwnPtr<ImageCacheEntry> createAndUse(const ImageFrameGenerator* generator, PassOwnPtr<ScaledImageFragment> image)
        {
            return adoptPtr(new ImageCacheEntry(generator, 1, image));
        }

        ImageCacheEntry(const ImageFrameGenerator* generator, int count, PassOwnPtr<ScaledImageFragment> image)
            : CacheEntry(generator, count, DiscardablePixelRef::isDiscardable(image->bitmap().pixelRef()))
            , m_cachedImage(image)
        {
        }

        // FIXME: getSafeSize() returns size in bytes truncated to a 32-bits integer.
        //        Find a way to get the size in 64-bits.
        virtual size_t memoryUsageInBytes() const { return cachedImage()->bitmap().getSafeSize(); }
        virtual CacheType type() const { return TypeImage; }

        static ImageCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size, size_t index, size_t generation)
        {
            return std::make_pair(std::make_pair(generator, size), std::make_pair(index, generation));
        }
        ImageCacheKey cacheKey() const { return makeCacheKey(m_generator, m_cachedImage->scaledSize(), m_cachedImage->index(), m_cachedImage->generation()); }
        const ScaledImageFragment* cachedImage() const { return m_cachedImage.get(); }
        ScaledImageFragment* cachedImage() { return m_cachedImage.get(); }

    private:
        OwnPtr<ScaledImageFragment> m_cachedImage;
    };

    class DecoderCacheEntry : public CacheEntry {
    public:
        static PassOwnPtr<DecoderCacheEntry> create(const ImageFrameGenerator* generator, PassOwnPtr<ImageDecoder> decoder, bool isDiscardable)
        {
            return adoptPtr(new DecoderCacheEntry(generator, 0, decoder, isDiscardable));
        }

        DecoderCacheEntry(const ImageFrameGenerator* generator, int count, PassOwnPtr<ImageDecoder> decoder, bool isDiscardable)
            : CacheEntry(generator, count, isDiscardable)
            , m_cachedDecoder(decoder)
            , m_size(SkISize::Make(m_cachedDecoder->size().width(), m_cachedDecoder->size().height()))
        {
        }

        virtual size_t memoryUsageInBytes() const { return m_size.width() * m_size.height() * 4; }
        virtual CacheType type() const { return TypeDecoder; }

        static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size)
        {
            return std::make_pair(generator, size);
        }
        static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const ImageDecoder* decoder)
        {
            return std::make_pair(generator, SkISize::Make(decoder->size().width(), decoder->size().height()));
        }
        DecoderCacheKey cacheKey() const { return makeCacheKey(m_generator, m_size); }
        ImageDecoder* cachedDecoder() const { return m_cachedDecoder.get(); }

    private:
        OwnPtr<ImageDecoder> m_cachedDecoder;
        SkISize m_size;
    };

    ImageDecodingStore();

    void prune();

    // These helper methods are called while m_mutex is locked.

    // Find and lock a cache entry, and return true on success.
    // Memory of the cache entry can be discarded, in which case it is saved in
    // deletionList.
    bool lockCacheEntryInternal(ImageCacheEntry*, const ScaledImageFragment**, Vector<OwnPtr<CacheEntry> >* deletionList);

    template<class T, class U, class V> void insertCacheInternal(PassOwnPtr<T> cacheEntry, U* cacheMap, V* identifierMap);

    // Helper method to remove a cache entry. Ownership is transferred to
    // deletionList. Use of Vector<> is handy when removing multiple entries.
    template<class T, class U, class V> void removeFromCacheInternal(const T* cacheEntry, U* cacheMap, V* identifierMap, Vector<OwnPtr<CacheEntry> >* deletionList);

    // Helper method to remove a cache entry. Uses the templated version base on
    // the type of cache entry.
    void removeFromCacheInternal(const CacheEntry*, Vector<OwnPtr<CacheEntry> >* deletionList);

    // Helper method to remove all cache entries associated with a ImageFraneGenerator.
    // Ownership of cache entries is transferred to deletionList.
    template<class U, class V> void removeCacheIndexedByGeneratorInternal(U* cacheMap, V* identifierMap, const ImageFrameGenerator*, Vector<OwnPtr<CacheEntry> >* deletionList);

    // Helper method to remove cache entry pointers from the LRU list.
    void removeFromCacheListInternal(const Vector<OwnPtr<CacheEntry> >& deletionList);

    void incrementMemoryUsage(size_t size) { m_memoryUsageInBytes += size; }
    void decrementMemoryUsage(size_t size)
    {
        ASSERT(m_memoryUsageInBytes >= size);
        m_memoryUsageInBytes -= size;
    }

    // A doubly linked list that maintains usage history of cache entries.
    // This is used for eviction of old entries.
    // Head of this list is the least recently used cache entry.
    // Tail of this list is the most recently used cache entry.
    DoublyLinkedList<CacheEntry> m_orderedCacheList;

    // A lookup table for all image cache objects. Owns all image cache objects.
    typedef HashMap<ImageCacheKey, OwnPtr<ImageCacheEntry> > ImageCacheMap;
    ImageCacheMap m_imageCacheMap;

    // A lookup table for all decoder cache objects. Owns all decoder cache objects.
    typedef HashMap<DecoderCacheKey, OwnPtr<DecoderCacheEntry> > DecoderCacheMap;
    DecoderCacheMap m_decoderCacheMap;

    // A lookup table to map ImageFrameGenerator to all associated image
    // cache keys.
    typedef HashSet<ImageCacheKey> ImageCacheKeySet;
    typedef HashMap<const ImageFrameGenerator*, ImageCacheKeySet> ImageCacheKeyMap;
    ImageCacheKeyMap m_imageCacheKeyMap;

    // A lookup table to map ImageFrameGenerator to all associated
    // decoder cache keys.
    typedef HashSet<DecoderCacheKey> DecoderCacheKeySet;
    typedef HashMap<const ImageFrameGenerator*, DecoderCacheKeySet> DecoderCacheKeyMap;
    DecoderCacheKeyMap m_decoderCacheKeyMap;

    size_t m_cacheLimitInBytes;
    size_t m_memoryUsageInBytes;

    // Protect concurrent access to these members:
    //   m_orderedCacheList
    //   m_imageCacheMap, m_decoderCacheMap and all CacheEntrys stored in it
    //   m_imageCacheKeyMap
    //   m_decoderCacheKeyMap
    //   m_cacheLimitInBytes
    //   m_memoryUsageInBytes
    // This mutex also protects calls to underlying skBitmap's
    // lockPixels()/unlockPixels() as they are not threadsafe.
    Mutex m_mutex;
};

} // namespace WebCore

#endif
