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

#include "include/utils/SkBase64.h"
#include "src/core/SkMD5.h"
#include "src/gpu/GrPersistentCacheUtils.h"
#include "tools/gpu/MemoryCache.h"

#if defined(SK_VULKAN)
#include "src/gpu/vk/GrVkGpu.h"
#endif

// Change this to 1 to log cache hits/misses/stores using SkDebugf.
#define LOG_MEMORY_CACHE 0

static SkString data_to_str(const SkData& data) {
    size_t encodeLength = SkBase64::Encode(data.data(), data.size(), nullptr);
    SkString str;
    str.resize(encodeLength);
    SkBase64::Encode(data.data(), data.size(), str.writable_str());
    static constexpr size_t kMaxLength = 60;
    static constexpr char kTail[] = "...";
    static const size_t kTailLen = strlen(kTail);
    bool overlength = encodeLength > kMaxLength;
    if (overlength) {
        str = SkString(str.c_str(), kMaxLength - kTailLen);
        str.append(kTail);
    }
    return str;
}

namespace sk_gpu_test {

sk_sp<SkData> MemoryCache::load(const SkData& key) {
    auto result = fMap.find(key);
    if (result == fMap.end()) {
        if (LOG_MEMORY_CACHE) {
            SkDebugf("Load Key: %s\n\tNot Found.\n\n", data_to_str(key).c_str());
        }
        ++fCacheMissCnt;
        return nullptr;
    }
    if (LOG_MEMORY_CACHE) {
        SkDebugf("Load Key: %s\n\tFound Data: %s\n\n", data_to_str(key).c_str(),
                 data_to_str(*result->second.fData).c_str());
    }
    result->second.fHitCount++;
    return result->second.fData;
}

void MemoryCache::store(const SkData& key, const SkData& data) {
    if (LOG_MEMORY_CACHE) {
        SkDebugf("Store Key: %s\n\tData: %s\n\n", data_to_str(key).c_str(),
                 data_to_str(data).c_str());
    }
    ++fCacheStoreCnt;
    fMap[Key(key)] = Value(data);
}

void MemoryCache::writeShadersToDisk(const char* path, GrBackendApi api) {
    if (GrBackendApi::kOpenGL != api && GrBackendApi::kVulkan != api) {
        return;
    }

    for (auto it = fMap.begin(); it != fMap.end(); ++it) {
        SkMD5 hash;
        size_t bytesToHash = it->first.fKey->size();
#if defined(SK_VULKAN)
        if (GrBackendApi::kVulkan == api) {
            // Vulkan stores two kinds of data in the cache (shaders and pipelines). The last four
            // bytes of the key identify which one we have. We only want to extract shaders.
            // Additionally, we don't want to hash the tag bytes, so we get the same keys as GL,
            // which is good for cross-checking code generation and performance.
            GrVkGpu::PersistentCacheKeyType vkKeyType;
            SkASSERT(bytesToHash >= sizeof(vkKeyType));
            bytesToHash -= sizeof(vkKeyType);
            memcpy(&vkKeyType, it->first.fKey->bytes() + bytesToHash, sizeof(vkKeyType));
            if (vkKeyType != GrVkGpu::kShader_PersistentCacheKeyType) {
                continue;
            }
        }
#endif
        hash.write(it->first.fKey->bytes(), bytesToHash);
        SkMD5::Digest digest = hash.finish();
        SkString md5;
        for (int i = 0; i < 16; ++i) {
            md5.appendf("%02x", digest.data[i]);
        }

        SkSL::Program::Inputs inputsIgnored[kGrShaderTypeCount];
        SkSL::String shaders[kGrShaderTypeCount];
        const SkData* data = it->second.fData.get();
        // Even with the SPIR-V switches, it seems like we must use .spv, or malisc tries to
        // run glslang on the input.
        const char* ext = GrBackendApi::kOpenGL == api ? "frag" : "spv";
        SkReadBuffer reader(data->data(), data->size());
        GrPersistentCacheUtils::GetType(&reader); // Shader type tag
        GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders,
                                                    inputsIgnored, kGrShaderTypeCount);

        SkString filename = SkStringPrintf("%s/%s.%s", path, md5.c_str(), ext);
        SkFILEWStream file(filename.c_str());
        file.write(shaders[kFragment_GrShaderType].c_str(), shaders[kFragment_GrShaderType].size());
    }
}

}  // namespace sk_gpu_test
