/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed 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.
 */

#include "ResourceCache.h"
#include "Caches.h"

namespace android {

using namespace uirenderer;
ANDROID_SINGLETON_STATIC_INSTANCE(ResourceCache);

namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// Resource cache
///////////////////////////////////////////////////////////////////////////////

void ResourceCache::logCache() {
    ALOGD("ResourceCache: cacheReport:");
    for (size_t i = 0; i < mCache->size(); ++i) {
        ResourceReference* ref = mCache->valueAt(i);
        ALOGD("  ResourceCache: mCache(%zu): resource, ref = 0x%p, 0x%p", i, mCache->keyAt(i),
              mCache->valueAt(i));
        ALOGD("  ResourceCache: mCache(%zu): refCount, destroyed, type = %d, %d, %d", i,
              ref->refCount, ref->destroyed, ref->resourceType);
    }
}

ResourceCache::ResourceCache() {
    Mutex::Autolock _l(mLock);
    mCache = new KeyedVector<const void*, ResourceReference*>();
}

ResourceCache::~ResourceCache() {
    Mutex::Autolock _l(mLock);
    delete mCache;
}

void ResourceCache::lock() {
    mLock.lock();
}

void ResourceCache::unlock() {
    mLock.unlock();
}

void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
    Mutex::Autolock _l(mLock);
    incrementRefcountLocked(resource, resourceType);
}

void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) {
    incrementRefcount((void*)patchResource, kNinePatch);
}

void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) {
    ssize_t index = mCache->indexOfKey(resource);
    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr;
    if (ref == nullptr || mCache->size() == 0) {
        ref = new ResourceReference(resourceType);
        mCache->add(resource, ref);
    }
    ref->refCount++;
}

void ResourceCache::decrementRefcount(void* resource) {
    Mutex::Autolock _l(mLock);
    decrementRefcountLocked(resource);
}

void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
    decrementRefcount((void*)patchResource);
}

void ResourceCache::decrementRefcountLocked(void* resource) {
    ssize_t index = mCache->indexOfKey(resource);
    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr;
    if (ref == nullptr) {
        // Should not get here - shouldn't get a call to decrement if we're not yet tracking it
        return;
    }
    ref->refCount--;
    if (ref->refCount == 0) {
        deleteResourceReferenceLocked(resource, ref);
    }
}

void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) {
    decrementRefcountLocked((void*)patchResource);
}

void ResourceCache::destructor(Res_png_9patch* resource) {
    Mutex::Autolock _l(mLock);
    destructorLocked(resource);
}

void ResourceCache::destructorLocked(Res_png_9patch* resource) {
    ssize_t index = mCache->indexOfKey(resource);
    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr;
    if (ref == nullptr) {
        // If we're not tracking this resource, just delete it
        if (Caches::hasInstance()) {
            Caches::getInstance().patchCache.removeDeferred(resource);
        } else {
            // A Res_png_9patch is actually an array of byte that's larger
            // than sizeof(Res_png_9patch). It must be freed as an array.
            delete[](int8_t*) resource;
        }
        return;
    }
    ref->destroyed = true;
    if (ref->refCount == 0) {
        deleteResourceReferenceLocked(resource, ref);
    }
}

/**
 * This method should only be called while the mLock mutex is held (that mutex is grabbed
 * by the various destructor() and recycle() methods which call this method).
 */
void ResourceCache::deleteResourceReferenceLocked(const void* resource, ResourceReference* ref) {
    if (ref->destroyed) {
        switch (ref->resourceType) {
            case kNinePatch: {
                if (Caches::hasInstance()) {
                    Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*)resource);
                } else {
                    // A Res_png_9patch is actually an array of byte that's larger
                    // than sizeof(Res_png_9patch). It must be freed as an array.
                    int8_t* patch = (int8_t*)resource;
                    delete[] patch;
                }
            } break;
        }
    }
    mCache->removeItem(resource);
    delete ref;
}

};  // namespace uirenderer
};  // namespace android
