// 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 <fstream>
#include <iterator>

#include "flutter/fml/build_config.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/paths.h"
#include "flutter/lib/ui/plugins/callback_cache.h"
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "third_party/tonic/converter/dart_converter.h"

using rapidjson::Document;
using rapidjson::StringBuffer;
using rapidjson::Writer;
using tonic::ToDart;

namespace flutter {

static const char* kHandleKey = "handle";
static const char* kRepresentationKey = "representation";
static const char* kNameKey = "name";
static const char* kClassNameKey = "class_name";
static const char* kLibraryPathKey = "library_path";
static const char* kCacheName = "flutter_callback_cache.json";
std::mutex DartCallbackCache::mutex_;
std::string DartCallbackCache::cache_path_;
std::map<int64_t, DartCallbackRepresentation> DartCallbackCache::cache_;

void DartCallbackCache::SetCachePath(const std::string& path) {
  cache_path_ = fml::paths::JoinPaths({path, kCacheName});
}

Dart_Handle DartCallbackCache::GetCallback(int64_t handle) {
  std::scoped_lock lock(mutex_);
  auto iterator = cache_.find(handle);
  if (iterator != cache_.end()) {
    DartCallbackRepresentation cb = iterator->second;
    return LookupDartClosure(cb.name, cb.class_name, cb.library_path);
  }
  return Dart_Null();
}

int64_t DartCallbackCache::GetCallbackHandle(const std::string& name,
                                             const std::string& class_name,
                                             const std::string& library_path) {
  std::scoped_lock lock(mutex_);
  std::hash<std::string> hasher;
  int64_t hash = hasher(name);
  hash += hasher(class_name);
  hash += hasher(library_path);

  if (cache_.find(hash) == cache_.end()) {
    cache_[hash] = {name, class_name, library_path};
    SaveCacheToDisk();
  }
  return hash;
}

std::unique_ptr<DartCallbackRepresentation>
DartCallbackCache::GetCallbackInformation(int64_t handle) {
  std::scoped_lock lock(mutex_);
  auto iterator = cache_.find(handle);
  if (iterator != cache_.end()) {
    return std::make_unique<DartCallbackRepresentation>(iterator->second);
  }
  return nullptr;
}

void DartCallbackCache::SaveCacheToDisk() {
  // Cache JSON format
  // [
  //   {
  //      "hash": 42,
  //      "representation": {
  //          "name": "...",
  //          "class_name": "...",
  //          "library_path": "..."
  //      }
  //   },
  //   {
  //   ...
  //   }
  // ]
  StringBuffer s;
  Writer<StringBuffer> writer(s);
  writer.StartArray();
  for (auto iterator = cache_.begin(); iterator != cache_.end(); ++iterator) {
    int64_t hash = iterator->first;
    DartCallbackRepresentation cb = iterator->second;
    writer.StartObject();
    writer.Key(kHandleKey);
    writer.Int64(hash);
    writer.Key(kRepresentationKey);
    writer.StartObject();
    writer.Key(kNameKey);
    writer.String(cb.name.c_str());
    writer.Key(kClassNameKey);
    writer.String(cb.class_name.c_str());
    writer.Key(kLibraryPathKey);
    writer.String(cb.library_path.c_str());
    writer.EndObject();
    writer.EndObject();
  }
  writer.EndArray();

  std::ofstream output(cache_path_);
  output << s.GetString();
  output.close();
}

void DartCallbackCache::LoadCacheFromDisk() {
  std::scoped_lock lock(mutex_);

  // Don't reload the cache if it's already populated.
  if (!cache_.empty()) {
    return;
  }
  std::ifstream input(cache_path_);
  if (!input) {
    return;
  }
  std::string cache_contents{std::istreambuf_iterator<char>(input),
                             std::istreambuf_iterator<char>()};
  Document d;
  d.Parse(cache_contents.c_str());
  if (d.HasParseError() || !d.IsArray()) {
    FML_LOG(WARNING) << "Could not parse callback cache, aborting restore";
    // TODO(bkonyi): log and bail (delete cache?)
    return;
  }
  const auto entries = d.GetArray();
  for (auto* it = entries.begin(); it != entries.end(); ++it) {
    const auto root_obj = it->GetObject();
    const auto representation = root_obj[kRepresentationKey].GetObject();

    const int64_t hash = root_obj[kHandleKey].GetInt64();
    DartCallbackRepresentation cb;
    cb.name = representation[kNameKey].GetString();
    cb.class_name = representation[kClassNameKey].GetString();
    cb.library_path = representation[kLibraryPathKey].GetString();
    cache_[hash] = cb;
  }
}

Dart_Handle DartCallbackCache::LookupDartClosure(
    const std::string& name,
    const std::string& class_name,
    const std::string& library_path) {
  Dart_Handle closure_name = ToDart(name);
  if (Dart_IsError(closure_name)) {
    return closure_name;
  }
  Dart_Handle library_name =
      library_path.empty() ? Dart_Null() : ToDart(library_path);
  if (Dart_IsError(library_name)) {
    return library_name;
  }
  Dart_Handle cls_name = class_name.empty() ? Dart_Null() : ToDart(class_name);
  if (Dart_IsError(cls_name)) {
    return cls_name;
  }

  Dart_Handle library;
  if (library_name == Dart_Null()) {
    library = Dart_RootLibrary();
  } else {
    library = Dart_LookupLibrary(library_name);
  }
  if (Dart_IsError(library)) {
    return library;
  }

  Dart_Handle closure;
  if (Dart_IsNull(cls_name)) {
    closure = Dart_GetField(library, closure_name);
  } else {
    Dart_Handle cls = Dart_GetClass(library, cls_name);
    if (Dart_IsError(cls)) {
      return cls;
    }
    if (Dart_IsNull(cls)) {
      closure = Dart_Null();
    } else {
      closure = Dart_GetStaticMethodClosure(library, cls, closure_name);
    }
  }
  return closure;
}

}  // namespace flutter
