// 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/shell/common/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/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 decoder;
  auto error = decoder.decode(input.c_str(), input.length());
  if (error != SkBase64::Error::kNoError) {
    FML_LOG(ERROR) << "Base64 decode error: " << error;
    FML_LOG(ERROR) << "Base64 can't decode: " << input;
    return nullptr;
  }
  return SkData::MakeWithCopy(decoder.getData(), decoder.getDataSize());
}

std::vector<PersistentCache::SkSLCache> PersistentCache::LoadSkSLs() {
  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;
}

}  // namespace flutter
