/*
 * 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 <utils/JenkinsHash.h>
#include <utils/Log.h>

#include "Caches.h"
#include "Patch.h"
#include "PatchCache.h"
#include "Properties.h"
#include "renderstate/RenderState.h"

namespace android {
namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////

PatchCache::PatchCache(RenderState& renderState)
        : mRenderState(renderState)
        , mMaxSize(KB(128))
        , mSize(0)
        , mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity)
        , mMeshBuffer(0)
        , mFreeBlocks(nullptr) {}

PatchCache::~PatchCache() {
    clear();
}

///////////////////////////////////////////////////////////////////////////////
// Caching
///////////////////////////////////////////////////////////////////////////////

hash_t PatchCache::PatchDescription::hash() const {
    uint32_t hash = JenkinsHashMix(0, android::hash_type(mPatch));
    hash = JenkinsHashMix(hash, mBitmapWidth);
    hash = JenkinsHashMix(hash, mBitmapHeight);
    hash = JenkinsHashMix(hash, mPixelWidth);
    hash = JenkinsHashMix(hash, mPixelHeight);
    return JenkinsHashWhiten(hash);
}

int PatchCache::PatchDescription::compare(const PatchCache::PatchDescription& lhs,
                                          const PatchCache::PatchDescription& rhs) {
    return memcmp(&lhs, &rhs, sizeof(PatchDescription));
}

void PatchCache::clear() {
    clearCache();

    if (mMeshBuffer) {
        mRenderState.meshState().deleteMeshBuffer(mMeshBuffer);
        mMeshBuffer = 0;
        mSize = 0;
    }
}

void PatchCache::clearCache() {
    LruCache<PatchDescription, Patch*>::Iterator i(mCache);
    while (i.next()) {
        delete i.value();
    }
    mCache.clear();

    BufferBlock* block = mFreeBlocks;
    while (block) {
        BufferBlock* next = block->next;
        delete block;
        block = next;
    }
    mFreeBlocks = nullptr;
}

void PatchCache::remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch) {
    LruCache<PatchDescription, Patch*>::Iterator i(mCache);
    while (i.next()) {
        const PatchDescription& key = i.key();
        if (key.getPatch() == patch) {
            patchesToRemove.push(patch_pair_t(&key, i.value()));
        }
    }
}

void PatchCache::removeDeferred(Res_png_9patch* patch) {
    Mutex::Autolock _l(mLock);

    // Assert that patch is not already garbage
    size_t count = mGarbage.size();
    for (size_t i = 0; i < count; i++) {
        if (patch == mGarbage[i]) {
            patch = nullptr;
            break;
        }
    }
    LOG_ALWAYS_FATAL_IF(patch == nullptr);

    mGarbage.push(patch);
}

void PatchCache::clearGarbage() {
    Vector<patch_pair_t> patchesToRemove;

    {  // scope for the mutex
        Mutex::Autolock _l(mLock);
        size_t count = mGarbage.size();
        for (size_t i = 0; i < count; i++) {
            Res_png_9patch* patch = mGarbage[i];
            remove(patchesToRemove, patch);
            // 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*) patch;
        }
        mGarbage.clear();
    }

    // TODO: We could sort patchesToRemove by offset to merge
    // adjacent free blocks
    for (size_t i = 0; i < patchesToRemove.size(); i++) {
        const patch_pair_t& pair = patchesToRemove[i];

        // Release the patch and mark the space in the free list
        Patch* patch = pair.getSecond();
        BufferBlock* block = new BufferBlock(patch->positionOffset, patch->getSize());
        block->next = mFreeBlocks;
        mFreeBlocks = block;

        mSize -= patch->getSize();

        mCache.remove(*pair.getFirst());
        delete patch;
    }

#if DEBUG_PATCHES
    if (patchesToRemove.size() > 0) {
        dumpFreeBlocks("Removed garbage");
    }
#endif
}

void PatchCache::createVertexBuffer() {
    mRenderState.meshState().genOrUpdateMeshBuffer(&mMeshBuffer, mMaxSize, nullptr,
                                                   GL_DYNAMIC_DRAW);
    mSize = 0;
    mFreeBlocks = new BufferBlock(0, mMaxSize);
}

/**
 * Sets the mesh's offsets and copies its associated vertices into
 * the mesh buffer (VBO).
 */
void PatchCache::setupMesh(Patch* newMesh) {
    // This call ensures the VBO exists and that it is bound
    if (!mMeshBuffer) {
        createVertexBuffer();
    }

    // If we're running out of space, let's clear the entire cache
    uint32_t size = newMesh->getSize();
    if (mSize + size > mMaxSize) {
        clearCache();
        createVertexBuffer();
    }

    // Find a block where we can fit the mesh
    BufferBlock* previous = nullptr;
    BufferBlock* block = mFreeBlocks;
    while (block) {
        // The mesh fits
        if (block->size >= size) {
            break;
        }
        previous = block;
        block = block->next;
    }

    // We have enough space left in the buffer, but it's
    // too fragmented, let's clear the cache
    if (!block) {
        clearCache();
        createVertexBuffer();
        previous = nullptr;
        block = mFreeBlocks;
    }

    // Copy the 9patch mesh in the VBO
    newMesh->positionOffset = (GLintptr)(block->offset);
    newMesh->textureOffset = newMesh->positionOffset + kMeshTextureOffset;

    mRenderState.meshState().updateMeshBufferSubData(mMeshBuffer, newMesh->positionOffset, size,
                                                     newMesh->vertices.get());

    // Remove the block since we've used it entirely
    if (block->size == size) {
        if (previous) {
            previous->next = block->next;
        } else {
            mFreeBlocks = block->next;
        }
        delete block;
    } else {
        // Resize the block now that it's occupied
        block->offset += size;
        block->size -= size;
    }

    mSize += size;
}

static const UvMapper sIdentity;

const Patch* PatchCache::get(const uint32_t bitmapWidth, const uint32_t bitmapHeight,
                             const float pixelWidth, const float pixelHeight,
                             const Res_png_9patch* patch) {
    const PatchDescription description(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, patch);
    const Patch* mesh = mCache.get(description);

    if (!mesh) {
        Patch* newMesh =
                new Patch(bitmapWidth, bitmapHeight, pixelWidth, pixelHeight, sIdentity, patch);

        if (newMesh->vertices) {
            setupMesh(newMesh);
        }

#if DEBUG_PATCHES
        dumpFreeBlocks("Adding patch");
#endif

        mCache.put(description, newMesh);
        return newMesh;
    }

    return mesh;
}

#if DEBUG_PATCHES
void PatchCache::dumpFreeBlocks(const char* prefix) {
    String8 dump;
    BufferBlock* block = mFreeBlocks;
    while (block) {
        dump.appendFormat("->(%d, %d)", block->positionOffset, block->size);
        block = block->next;
    }
    ALOGD("%s: Free blocks%s", prefix, dump.string());
}
#endif

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