/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkThread.h"
#include "SkPurgeableImageCache.h"
#include "SkPurgeableMemoryBlock.h"

#ifdef SK_DEBUG
    #include "SkTSearch.h"
#endif

SK_DEFINE_INST_COUNT(SkPurgeableImageCache)
SK_DECLARE_STATIC_MUTEX(gPurgeableImageMutex);

SkImageCache* SkPurgeableImageCache::Create() {
    if (!SkPurgeableMemoryBlock::IsSupported()) {
        return NULL;
    }
    SkAutoMutexAcquire ac(&gPurgeableImageMutex);
    static SkPurgeableImageCache gCache;
    gCache.ref();
    return &gCache;
}

SkPurgeableImageCache::SkPurgeableImageCache() {}

#ifdef SK_DEBUG
SkPurgeableImageCache::~SkPurgeableImageCache() {
    SkASSERT(fRecs.count() == 0);
}
#endif


void* SkPurgeableImageCache::allocAndPinCache(size_t bytes, intptr_t* ID) {
    SkAutoMutexAcquire ac(&gPurgeableImageMutex);

    SkPurgeableMemoryBlock* block = SkPurgeableMemoryBlock::Create(bytes);
    if (NULL == block) {
        return NULL;
    }

    SkPurgeableMemoryBlock::PinResult pinResult;
    void* data = block->pin(&pinResult);
    if (NULL == data) {
        SkDELETE(block);
        return NULL;
    }

    SkASSERT(ID != NULL);
    *ID = reinterpret_cast<intptr_t>(block);
#ifdef SK_DEBUG
    // Insert into the array of all recs:
    int index = this->findRec(*ID);
    SkASSERT(index < 0);
    fRecs.insert(~index, 1, ID);
#endif
    return data;
}

void* SkPurgeableImageCache::pinCache(intptr_t ID, SkImageCache::DataStatus* status) {
    SkASSERT(ID != SkImageCache::UNINITIALIZED_ID);
    SkAutoMutexAcquire ac(&gPurgeableImageMutex);

    SkASSERT(this->findRec(ID) >= 0);
    SkPurgeableMemoryBlock* block = reinterpret_cast<SkPurgeableMemoryBlock*>(ID);
    SkPurgeableMemoryBlock::PinResult pinResult;
    void* data = block->pin(&pinResult);
    if (NULL == data) {
        this->removeRec(ID);
        return NULL;
    }

    switch (pinResult) {
        case SkPurgeableMemoryBlock::kRetained_PinResult:
            *status = SkImageCache::kRetained_DataStatus;
            break;

        case SkPurgeableMemoryBlock::kUninitialized_PinResult:
            *status = SkImageCache::kUninitialized_DataStatus;
            break;

        default:
            // Invalid value. Treat as a failure to pin.
            SkASSERT(false);
            this->removeRec(ID);
            return NULL;
    }

    return data;
}

void SkPurgeableImageCache::releaseCache(intptr_t ID) {
    SkASSERT(ID != SkImageCache::UNINITIALIZED_ID);
    SkAutoMutexAcquire ac(&gPurgeableImageMutex);

    SkASSERT(this->findRec(ID) >= 0);
    SkPurgeableMemoryBlock* block = reinterpret_cast<SkPurgeableMemoryBlock*>(ID);
    block->unpin();
}

void SkPurgeableImageCache::throwAwayCache(intptr_t ID) {
    SkASSERT(ID != SkImageCache::UNINITIALIZED_ID);
    SkAutoMutexAcquire ac(&gPurgeableImageMutex);

    this->removeRec(ID);
}

#ifdef SK_DEBUG
SkImageCache::MemoryStatus SkPurgeableImageCache::getMemoryStatus(intptr_t ID) const {
    SkAutoMutexAcquire ac(&gPurgeableImageMutex);
    if (SkImageCache::UNINITIALIZED_ID == ID || this->findRec(ID) < 0) {
        return SkImageCache::kFreed_MemoryStatus;
    }

    SkPurgeableMemoryBlock* block = reinterpret_cast<SkPurgeableMemoryBlock*>(ID);
    if (block->isPinned()) {
        return SkImageCache::kPinned_MemoryStatus;
    }
    return SkImageCache::kUnpinned_MemoryStatus;
}

void SkPurgeableImageCache::purgeAllUnpinnedCaches() {
    SkAutoMutexAcquire ac(&gPurgeableImageMutex);
    if (SkPurgeableMemoryBlock::PlatformSupportsPurgingAllUnpinnedBlocks()) {
        SkPurgeableMemoryBlock::PurgeAllUnpinnedBlocks();
    } else {
        // Go through the blocks, and purge them individually.
        // Rather than deleting the blocks, which would interfere with further calls, purge them
        // and keep them around.
        for (int i = 0; i < fRecs.count(); i++) {
            SkPurgeableMemoryBlock* block = reinterpret_cast<SkPurgeableMemoryBlock*>(fRecs[i]);
            if (!block->isPinned()) {
                if (!block->purge()) {
                    // FIXME: This should be more meaningful (which one, etc...)
                    SkDebugf("Failed to purge\n");
                }
            }
        }
    }
}

int SkPurgeableImageCache::findRec(intptr_t rec) const {
    return SkTSearch(fRecs.begin(), fRecs.count(), rec, sizeof(intptr_t));
}
#endif

void SkPurgeableImageCache::removeRec(intptr_t ID) {
#ifdef SK_DEBUG
    int index = this->findRec(ID);
    SkASSERT(index >= 0);
    fRecs.remove(index);
#endif
    SkPurgeableMemoryBlock* block = reinterpret_cast<SkPurgeableMemoryBlock*>(ID);
    SkASSERT(!block->isPinned());
    SkDELETE(block);
}
