// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/common/graphics/persistent_cache.h"

#include <future>
#include <memory>
#include <string>
#include <string_view>

#include "flutter/fml/base32.h"
#include "flutter/fml/file.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/mapping.h"
#include "flutter/fml/paths.h"
#include "flutter/fml/trace_event.h"
#include "flutter/shell/version/version.h"
#include "rapidjson/document.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/utils/SkBase64.h"

namespace flutter {

std::string PersistentCache::cache_base_path_;

std::shared_ptr<AssetManager> PersistentCache::asset_manager_;

std::mutex PersistentCache::instance_mutex_;
std::unique_ptr<PersistentCache> PersistentCache::gPersistentCache;

std::string PersistentCache::SkKeyToFilePath(const SkData& data) {
  if (data.data() == nullptr || data.size() == 0) {
    return "";
  }

  std::string_view view(reinterpret_cast<const char*>(data.data()),
                        data.size());

  auto encode_result = fml::Base32Encode(view);

  if (!encode_result.first) {
    return "";
  }

  return encode_result.second;
}

bool PersistentCache::gIsReadOnly = false;

std::atomic<bool> PersistentCache::cache_sksl_ = false;
std::atomic<bool> PersistentCache::strategy_set_ = false;

void PersistentCache::SetCacheSkSL(bool value) {
  if (strategy_set_ && value != cache_sksl_) {
    FML_LOG(ERROR) << "Cache SkSL can only be set before the "
                      "GrContextOptions::fShaderCacheStrategy is set.";
    return;
  }
  cache_sksl_ = value;
}

PersistentCache* PersistentCache::GetCacheForProcess() {
  std::scoped_lock lock(instance_mutex_);
  if (gPersistentCache == nullptr) {
    gPersistentCache.reset(new PersistentCache(gIsReadOnly));
  }
  return gPersistentCache.get();
}

void PersistentCache::ResetCacheForProcess() {
  std::scoped_lock lock(instance_mutex_);
  gPersistentCache.reset(new PersistentCache(gIsReadOnly));
  strategy_set_ = false;
}

void PersistentCache::SetCacheDirectoryPath(std::string path) {
  cache_base_path_ = path;
}

bool PersistentCache::Purge() {
  // Make sure that this is called after the worker task runner setup so all the
  // file system modifications would happen on that single thread to avoid
  // racing.
  FML_CHECK(GetWorkerTaskRunner());

  std::promise<bool> removed;
  GetWorkerTaskRunner()->PostTask([&removed,
                                   cache_directory = cache_directory_]() {
    if (cache_directory->is_valid()) {
      // Only remove files but not directories.
      FML_LOG(INFO) << "Purge persistent cache.";
      fml::FileVisitor delete_file = [](const fml::UniqueFD& directory,
                                        const std::string& filename) {
        // Do not delete directories. Return true to continue with other files.
        if (fml::IsDirectory(directory, filename.c_str())) {
          return true;
        }
        return fml::UnlinkFile(directory, filename.c_str());
      };
      removed.set_value(VisitFilesRecursively(*cache_directory, delete_file));
    } else {
      removed.set_value(false);
    }
  });
  return removed.get_future().get();
}

namespace {

constexpr char kEngineComponent[] = "flutter_engine";

static void FreeOldCacheDirectory(const fml::UniqueFD& cache_base_dir) {
  fml::UniqueFD engine_dir =
      fml::OpenDirectoryReadOnly(cache_base_dir, kEngineComponent);
  if (!engine_dir.is_valid()) {
    return;
  }
  fml::VisitFiles(engine_dir, [](const fml::UniqueFD& directory,
                                 const std::string& filename) {
    if (filename != GetFlutterEngineVersion()) {
      auto dir = fml::OpenDirectory(directory, filename.c_str(), false,
                                    fml::FilePermission::kReadWrite);
      if (dir.is_valid()) {
        fml::RemoveDirectoryRecursively(directory, filename.c_str());
      }
    }
    return true;
  });
}

static std::shared_ptr<fml::UniqueFD> MakeCacheDirectory(
    const std::string& global_cache_base_path,
    bool read_only,
    bool cache_sksl) {
  fml::UniqueFD cache_base_dir;
  if (global_cache_base_path.length()) {
    cache_base_dir = fml::OpenDirectory(global_cache_base_path.c_str(), false,
                                        fml::FilePermission::kRead);
  } else {
    cache_base_dir = fml::paths::GetCachesDirectory();
  }

  if (cache_base_dir.is_valid()) {
    FreeOldCacheDirectory(cache_base_dir);
    std::vector<std::string> components = {
        kEngineComponent, GetFlutterEngineVersion(), "skia", GetSkiaVersion()};
    if (cache_sksl) {
      components.push_back(PersistentCache::kSkSLSubdirName);
    }
    return std::make_shared<fml::UniqueFD>(
        CreateDirectory(cache_base_dir, components,
                        read_only ? fml::FilePermission::kRead
                                  : fml::FilePermission::kReadWrite));
  } else {
    return std::make_shared<fml::UniqueFD>();
  }
}
}  // namespace

sk_sp<SkData> ParseBase32(const std::string& input) {
  std::pair<bool, std::string> decode_result = fml::Base32Decode(input);
  if (!decode_result.first) {
    FML_LOG(ERROR) << "Base32 can't decode: " << input;
    return nullptr;
  }
  const std::string& data_string = decode_result.second;
  return SkData::MakeWithCopy(data_string.data(), data_string.length());
}

sk_sp<SkData> ParseBase64(const std::string& input) {
  SkBase64::Error error;

  size_t output_len;
  error = SkBase64::Decode(input.c_str(), input.length(), nullptr, &output_len);
  if (error != SkBase64::Error::kNoError) {
    FML_LOG(ERROR) << "Base64 decode error: " << error;
    FML_LOG(ERROR) << "Base64 can't decode: " << input;
    return nullptr;
  }

  sk_sp<SkData> data = SkData::MakeUninitialized(output_len);
  void* output = data->writable_data();
  error = SkBase64::Decode(input.c_str(), input.length(), output, &output_len);
  if (error != SkBase64::Error::kNoError) {
    FML_LOG(ERROR) << "Base64 decode error: " << error;
    FML_LOG(ERROR) << "Base64 can't decode: " << input;
    return nullptr;
  }

  return data;
}

size_t PersistentCache::PrecompileKnownSkSLs(GrDirectContext* context) const {
  auto known_sksls = LoadSkSLs();
  // A trace must be present even if no precompilations have been completed.
  FML_TRACE_EVENT("flutter", "PersistentCache::PrecompileKnownSkSLs", "count",
                  known_sksls.size());

  if (context == nullptr) {
    return 0;
  }

  size_t precompiled_count = 0;
  for (const auto& sksl : known_sksls) {
    TRACE_EVENT0("flutter", "PrecompilingSkSL");
    if (context->precompileShader(*sksl.first, *sksl.second)) {
      precompiled_count++;
    }
  }

  FML_TRACE_COUNTER("flutter", "PersistentCache::PrecompiledSkSLs",
                    reinterpret_cast<int64_t>(this),  // Trace Counter ID
                    "Successful", precompiled_count);
  return precompiled_count;
}

std::vector<PersistentCache::SkSLCache> PersistentCache::LoadSkSLs() const {
  TRACE_EVENT0("flutter", "PersistentCache::LoadSkSLs");
  std::vector<PersistentCache::SkSLCache> result;
  fml::FileVisitor visitor = [&result](const fml::UniqueFD& directory,
                                       const std::string& filename) {
    sk_sp<SkData> key = ParseBase32(filename);
    sk_sp<SkData> data = LoadFile(directory, filename);
    if (key != nullptr && data != nullptr) {
      result.push_back({key, data});
    } else {
      FML_LOG(ERROR) << "Failed to load: " << filename;
    }
    return true;
  };

  // Only visit sksl_cache_directory_ if this persistent cache is valid.
  // However, we'd like to continue visit the asset dir even if this persistent
  // cache is invalid.
  if (IsValid()) {
    // In case `rewinddir` doesn't work reliably, load SkSLs from a freshly
    // opened directory (https://github.com/flutter/flutter/issues/65258).
    fml::UniqueFD fresh_dir =
        fml::OpenDirectoryReadOnly(*cache_directory_, kSkSLSubdirName);
    if (fresh_dir.is_valid()) {
      fml::VisitFiles(fresh_dir, visitor);
    }
  }

  std::unique_ptr<fml::Mapping> mapping = nullptr;
  if (asset_manager_ != nullptr) {
    mapping = asset_manager_->GetAsMapping(kAssetFileName);
  }
  if (mapping == nullptr) {
    FML_LOG(INFO) << "No sksl asset found.";
  } else {
    FML_LOG(INFO) << "Found sksl asset. Loading SkSLs from it...";
    rapidjson::Document json_doc;
    rapidjson::ParseResult parse_result =
        json_doc.Parse(reinterpret_cast<const char*>(mapping->GetMapping()),
                       mapping->GetSize());
    if (parse_result != rapidjson::ParseErrorCode::kParseErrorNone) {
      FML_LOG(ERROR) << "Failed to parse json file: " << kAssetFileName;
    } else {
      for (auto& item : json_doc["data"].GetObject()) {
        sk_sp<SkData> key = ParseBase32(item.name.GetString());
        sk_sp<SkData> sksl = ParseBase64(item.value.GetString());
        if (key != nullptr && sksl != nullptr) {
          result.push_back({key, sksl});
        } else {
          FML_LOG(ERROR) << "Failed to load: " << item.name.GetString();
        }
      }
    }
  }

  return result;
}

PersistentCache::PersistentCache(bool read_only)
    : is_read_only_(read_only),
      cache_directory_(MakeCacheDirectory(cache_base_path_, read_only, false)),
      sksl_cache_directory_(
          MakeCacheDirectory(cache_base_path_, read_only, true)) {
  if (!IsValid()) {
    FML_LOG(WARNING) << "Could not acquire the persistent cache directory. "
                        "Caching of GPU resources on disk is disabled.";
  }
}

PersistentCache::~PersistentCache() = default;

bool PersistentCache::IsValid() const {
  return cache_directory_ && cache_directory_->is_valid();
}

sk_sp<SkData> PersistentCache::LoadFile(const fml::UniqueFD& dir,
                                        const std::string& file_name) {
  auto file = fml::OpenFileReadOnly(dir, file_name.c_str());
  if (!file.is_valid()) {
    return nullptr;
  }
  auto mapping = std::make_unique<fml::FileMapping>(file);
  if (mapping->GetSize() == 0) {
    return nullptr;
  }
  return SkData::MakeWithCopy(mapping->GetMapping(), mapping->GetSize());
}

// |GrContextOptions::PersistentCache|
sk_sp<SkData> PersistentCache::load(const SkData& key) {
  TRACE_EVENT0("flutter", "PersistentCacheLoad");
  if (!IsValid()) {
    return nullptr;
  }
  auto file_name = SkKeyToFilePath(key);
  if (file_name.size() == 0) {
    return nullptr;
  }
  auto result = PersistentCache::LoadFile(*cache_directory_, file_name);
  if (result != nullptr) {
    TRACE_EVENT0("flutter", "PersistentCacheLoadHit");
  }
  return result;
}

static void PersistentCacheStore(fml::RefPtr<fml::TaskRunner> worker,
                                 std::shared_ptr<fml::UniqueFD> cache_directory,
                                 std::string key,
                                 std::unique_ptr<fml::Mapping> value) {
  auto task = fml::MakeCopyable([cache_directory,             //
                                 file_name = std::move(key),  //
                                 mapping = std::move(value)   //
  ]() mutable {
    TRACE_EVENT0("flutter", "PersistentCacheStore");
    if (!fml::WriteAtomically(*cache_directory,   //
                              file_name.c_str(),  //
                              *mapping)           //
    ) {
      FML_LOG(WARNING) << "Could not write cache contents to persistent store.";
    }
  });

  if (!worker) {
    FML_LOG(WARNING)
        << "The persistent cache has no available workers. Performing the task "
           "on the current thread. This slow operation is going to occur on a "
           "frame workload.";
    task();
  } else {
    worker->PostTask(std::move(task));
  }
}

// |GrContextOptions::PersistentCache|
void PersistentCache::store(const SkData& key, const SkData& data) {
  stored_new_shaders_ = true;

  if (is_read_only_) {
    return;
  }

  if (!IsValid()) {
    return;
  }

  auto file_name = SkKeyToFilePath(key);

  if (file_name.size() == 0) {
    return;
  }

  auto mapping = std::make_unique<fml::DataMapping>(
      std::vector<uint8_t>{data.bytes(), data.bytes() + data.size()});

  if (mapping == nullptr || mapping->GetSize() == 0) {
    return;
  }

  PersistentCacheStore(GetWorkerTaskRunner(),
                       cache_sksl_ ? sksl_cache_directory_ : cache_directory_,
                       std::move(file_name), std::move(mapping));
}

void PersistentCache::DumpSkp(const SkData& data) {
  if (is_read_only_ || !IsValid()) {
    FML_LOG(ERROR) << "Could not dump SKP from read-only or invalid persistent "
                      "cache.";
    return;
  }

  std::stringstream name_stream;
  auto ticks = fml::TimePoint::Now().ToEpochDelta().ToNanoseconds();
  name_stream << "shader_dump_" << std::to_string(ticks) << ".skp";
  std::string file_name = name_stream.str();
  FML_LOG(INFO) << "Dumping " << file_name;
  auto mapping = std::make_unique<fml::DataMapping>(
      std::vector<uint8_t>{data.bytes(), data.bytes() + data.size()});
  PersistentCacheStore(GetWorkerTaskRunner(), cache_directory_,
                       std::move(file_name), std::move(mapping));
}

void PersistentCache::AddWorkerTaskRunner(
    fml::RefPtr<fml::TaskRunner> task_runner) {
  std::scoped_lock lock(worker_task_runners_mutex_);
  worker_task_runners_.insert(task_runner);
}

void PersistentCache::RemoveWorkerTaskRunner(
    fml::RefPtr<fml::TaskRunner> task_runner) {
  std::scoped_lock lock(worker_task_runners_mutex_);
  auto found = worker_task_runners_.find(task_runner);
  if (found != worker_task_runners_.end()) {
    worker_task_runners_.erase(found);
  }
}

fml::RefPtr<fml::TaskRunner> PersistentCache::GetWorkerTaskRunner() const {
  fml::RefPtr<fml::TaskRunner> worker;

  std::scoped_lock lock(worker_task_runners_mutex_);
  if (!worker_task_runners_.empty()) {
    worker = *worker_task_runners_.begin();
  }

  return worker;
}

void PersistentCache::SetAssetManager(std::shared_ptr<AssetManager> value) {
  TRACE_EVENT_INSTANT0("flutter", "PersistentCache::SetAssetManager");
  asset_manager_ = value;
}

std::vector<std::unique_ptr<fml::Mapping>>
PersistentCache::GetSkpsFromAssetManager() const {
  if (!asset_manager_) {
    FML_LOG(ERROR)
        << "PersistentCache::GetSkpsFromAssetManager: Asset manager not set!";
    return std::vector<std::unique_ptr<fml::Mapping>>();
  }
  return asset_manager_->GetAsMappings(".*\\.skp$", "shaders");
}

}  // namespace flutter
