/*
 * Copyright 2017 Google Inc.
 *
 * 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 "fuchsia_font_manager.h"

#include <lib/fit/function.h>
#include <trace/event.h>
#include <lib/zx/vmar.h>

#include <unordered_map>

#include "third_party/icu/source/common/unicode/uchar.h"
#include "topaz/runtime/dart/utils/inlines.h"
#include "topaz/runtime/dart/utils/vmo.h"

#include "topaz/runtime/flutter_runner/logging.h"

namespace txt {

namespace {

constexpr char kDefaultFontFamily[] = "Roboto";

void UnmapMemory(const void* buffer, uint64_t size) {
  static_assert(sizeof(void*) == sizeof(uint64_t), "pointers aren't 64-bit");
  zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(buffer), size);
}

struct ReleaseSkDataContext {
  uint64_t buffer_size;
  int buffer_id;
  fit::function<void()> release_proc;

  ReleaseSkDataContext(uint64_t buffer_size, int buffer_id,
                       fit::function<void()> release_proc)
      : buffer_size(buffer_size),
        buffer_id(buffer_id),
        release_proc(std::move(release_proc)) {}
};

void ReleaseSkData(const void* buffer, void* context) {
  auto skdata_context = reinterpret_cast<ReleaseSkDataContext*>(context);
  DEBUG_CHECK(skdata_context != nullptr, LOG_TAG, "");
  UnmapMemory(buffer, skdata_context->buffer_size);
  skdata_context->release_proc();
  delete skdata_context;
}

sk_sp<SkData> MakeSkDataFromBuffer(const fuchsia::mem::Buffer& data,
                                   int buffer_id,
                                   fit::function<void()> release_proc) {
  bool is_valid;
  zx_status_t status = dart_utils::IsSizeValid(data, &is_valid);
  if (!is_valid || data.size > std::numeric_limits<size_t>::max()) {
    return nullptr;
  }
  uint64_t size = data.size;
  uintptr_t buffer = 0;
  status = zx::vmar::root_self()->map(0, data.vmo, 0, size, ZX_VM_PERM_READ,
                                      &buffer);
  if (status != ZX_OK)
    return nullptr;
  auto context =
      new ReleaseSkDataContext(size, buffer_id, std::move(release_proc));
  return SkData::MakeWithProc(reinterpret_cast<void*>(buffer), size,
                              ReleaseSkData, context);
}

fuchsia::fonts::Slant SkToFuchsiaSlant(SkFontStyle::Slant slant) {
  switch (slant) {
    case SkFontStyle::kOblique_Slant:
      return fuchsia::fonts::Slant::OBLIQUE;
    case SkFontStyle::kItalic_Slant:
      return fuchsia::fonts::Slant::ITALIC;
    case SkFontStyle::kUpright_Slant:
    default:
      return fuchsia::fonts::Slant::UPRIGHT;
  }
}

SkFontStyle::Slant FuchsiaToSkSlant(fuchsia::fonts::Slant slant) {
  switch (slant) {
    case fuchsia::fonts::Slant::OBLIQUE:
      return SkFontStyle::kOblique_Slant;
    case fuchsia::fonts::Slant::ITALIC:
      return SkFontStyle::kItalic_Slant;
    case fuchsia::fonts::Slant::UPRIGHT:
    default:
      return SkFontStyle::kUpright_Slant;
  }
}

fidl::VectorPtr<std::string> BuildLanguageList(const char* bcp47[],
                                               int bcp47_count) {
  DEBUG_CHECK(bcp47 != nullptr || bcp47_count == 0, LOG_TAG, "");
  auto languages = fidl::VectorPtr<std::string>::New(0);
  for (int i = 0; i < bcp47_count; i++) {
    languages.push_back(bcp47[i]);
  }
  return languages;
}

sk_sp<SkTypeface> CreateTypefaceFromSkData(sk_sp<SkData> data, int font_index) {
  return SkFontMgr::RefDefault()->makeFromData(std::move(data), font_index);
}

}  // anonymous namespace

class FuchsiaFontManager::TypefaceCache {
 public:
  TypefaceCache() {}
  ~TypefaceCache();

  // Get an SkTypeface with the given buffer id, font index, and buffer
  // data. Creates a new SkTypeface if one does not already exist.
  sk_sp<SkTypeface> GetOrCreateTypeface(
      int buffer_id, int font_index, const fuchsia::mem::Buffer& buffer) const;

  // Callback called when an SkData with the given buffer id is deleted.
  void OnSkDataDeleted(int buffer_id) const;

 private:
  // Used to identify an SkTypeface in the cache.
  struct TypefaceId {
    int buffer_id;
    int font_index;

    // Needed by std::unordered_map.
    bool operator==(const TypefaceId& other) const {
      return (buffer_id == other.buffer_id && font_index == other.font_index);
    }

    // Used for debugging.
    friend std::ostream& operator<<(std::ostream& os, const TypefaceId& id) {
      return os << "TypfaceId: [buffer_id: " << id.buffer_id
                << ", font_index: " << id.font_index << "]";
    }
  };

  // Needed by std::unordered_map.
  struct TypefaceIdHash {
    std::size_t operator()(const TypefaceId& id) const {
      return std::hash<int>()(id.buffer_id) ^
             (std::hash<int>()(id.font_index) << 1);
    }
  };

  // Try to get an SkData with the given buffer id from the cache. If an
  // SkData is not found, create it and add it to the cache.
  sk_sp<SkData> GetOrCreateSkData(int buffer_id,
                                  const fuchsia::mem::Buffer& buffer) const;

  // Create a new SkTypeface for the given TypefaceId and SkData and add it to
  // the cache.
  sk_sp<SkTypeface> CreateSkTypeface(TypefaceId id, sk_sp<SkData> buffer) const;

  mutable std::unordered_map<TypefaceId, SkTypeface*, TypefaceIdHash>
      typeface_cache_;
  mutable std::unordered_map<int, std::shared_ptr<BufferHolder>> buffer_cache_;

  // Disallow copy and assignment.
  TypefaceCache(const TypefaceCache&) = delete;
  TypefaceCache& operator=(const TypefaceCache&) = delete;
};

class FuchsiaFontManager::BufferHolder {
 public:
  BufferHolder(const TypefaceCache* cache, int buffer_id) :
      cache_(cache), buffer_id_(buffer_id) {}
  ~BufferHolder() {}

  void SetData(SkData* data) { data_ = data; }

  SkData* GetData() const { return data_; }

  void OnDataDeleted() {
    cache_->OnSkDataDeleted(buffer_id_);
  }

 private:
  const TypefaceCache* cache_;
  int buffer_id_;
  SkData* data_;

  // Disallow copy and assignment.
  BufferHolder(const BufferHolder&) = delete;
  BufferHolder& operator=(const BufferHolder&) = delete;
};

FuchsiaFontManager::TypefaceCache::~TypefaceCache() {
  for (const auto& entry : typeface_cache_) {
    entry.second->weak_unref();
  }
}

void FuchsiaFontManager::TypefaceCache::OnSkDataDeleted(int buffer_id) const {
  bool was_found = buffer_cache_.erase(buffer_id) != 0;
  DEBUG_CHECK(was_found, LOG_TAG, "");
}

sk_sp<SkData> FuchsiaFontManager::TypefaceCache::GetOrCreateSkData(
    int buffer_id, const fuchsia::mem::Buffer& buffer) const {
  auto iter = buffer_cache_.find(buffer_id);
  if (iter != buffer_cache_.end()) {
    return sk_ref_sp(iter->second->GetData());
  }
  auto holder = std::make_shared<BufferHolder>(this, buffer_id);
  std::weak_ptr<BufferHolder> weak_holder = holder;
  auto data = MakeSkDataFromBuffer(buffer, buffer_id, [weak_holder]() {
    if (auto holder = weak_holder.lock()) {
      holder->OnDataDeleted();
    }
  });
  if (!data) {
    return nullptr;
  }
  holder->SetData(data.get());
  buffer_cache_[buffer_id] = std::move(holder);
  return data;
}

sk_sp<SkTypeface> FuchsiaFontManager::TypefaceCache::CreateSkTypeface(
    TypefaceId id, sk_sp<SkData> buffer) const {
  auto result = CreateTypefaceFromSkData(std::move(buffer), id.font_index);
  result->weak_ref();
  typeface_cache_[id] = result.get();
  return result;
}

sk_sp<SkTypeface> FuchsiaFontManager::TypefaceCache::GetOrCreateTypeface(
    int buffer_id, int font_index, const fuchsia::mem::Buffer& buffer) const {
  auto id = TypefaceId{buffer_id, font_index};
  auto iter = typeface_cache_.find(id);
  if (iter != typeface_cache_.end()) {
    if (iter->second->try_ref()) {
      return sk_ref_sp(iter->second);
    } else {
      iter->second->weak_unref();
      typeface_cache_.erase(iter);
    }
  }
  sk_sp<SkData> data = GetOrCreateSkData(buffer_id, buffer);
  if (!data) {
    return nullptr;
  }
  return CreateSkTypeface(id, std::move(data));
}

class FuchsiaFontManager::FontStyleSet : public SkFontStyleSet {
 public:
  FontStyleSet(sk_sp<FuchsiaFontManager> font_manager, std::string family_name,
               std::vector<SkFontStyle> styles)
      : font_manager_(font_manager),
        family_name_(family_name),
        styles_(styles) {}

  ~FontStyleSet() override = default;

  int count() override { return styles_.size(); }

  void getStyle(int index, SkFontStyle* style, SkString* style_name) override {
    DEBUG_CHECK(
        index >= 0 && index < static_cast<int>(styles_.size()), LOG_TAG, "");
    if (style)
      *style = styles_[index];

    // We don't have style names. Return an empty name.
    if (style_name)
      style_name->reset();
  }

  SkTypeface* createTypeface(int index) override {
    DEBUG_CHECK(
        index >= 0 && index < static_cast<int>(styles_.size()), LOG_TAG, "");

    if (typefaces_.empty())
      typefaces_.resize(styles_.size());

    if (!typefaces_[index]) {
      typefaces_[index] = font_manager_->FetchTypeface(
          family_name_.c_str(), styles_[index], /*bcp47=*/nullptr,
          /*bcp47_count=*/0, /*character=*/0,
          fuchsia::fonts::REQUEST_FLAG_NO_FALLBACK |
              fuchsia::fonts::REQUEST_FLAG_EXACT_MATCH);
    }

    return SkSafeRef(typefaces_[index].get());
  }

  SkTypeface* matchStyle(const SkFontStyle& pattern) override {
    return matchStyleCSS3(pattern);
  }

 private:
  sk_sp<FuchsiaFontManager> font_manager_;
  std::string family_name_;
  std::vector<SkFontStyle> styles_;
  std::vector<sk_sp<SkTypeface>> typefaces_;

  // Disallow copy and assignment.
  FontStyleSet(const FontStyleSet&) = delete;
  FontStyleSet& operator=(const FontStyleSet&) = delete;
};

FuchsiaFontManager::FuchsiaFontManager(fuchsia::fonts::ProviderSyncPtr provider)
    : font_provider_(std::move(provider)),
      typeface_cache_(new FuchsiaFontManager::TypefaceCache()) {}

FuchsiaFontManager::~FuchsiaFontManager() = default;

int FuchsiaFontManager::onCountFamilies() const {
  DEBUG_CHECK(false, LOG_TAG, "");
  return 0;
}

void FuchsiaFontManager::onGetFamilyName(int index,
                                         SkString* familyName) const {
  DEBUG_CHECK(false, LOG_TAG, "");
}

SkFontStyleSet* FuchsiaFontManager::onCreateStyleSet(int index) const {
  DEBUG_CHECK(false, LOG_TAG, "");
  return nullptr;
}

SkFontStyleSet* FuchsiaFontManager::onMatchFamily(
    const char family_name[]) const {
  fuchsia::fonts::FamilyInfoPtr family_info;
  int err = font_provider_->GetFamilyInfo(family_name, &family_info);
  if (err != ZX_OK) {
#ifndef NDEBUG
    FX_LOGF(ERROR, LOG_TAG, "Error fetching family from provider [err=%d]. Did "
            "you run Flutter in an environment that has a font manager?", err);
#endif
    return nullptr;
  }

  if (!family_info)
    return nullptr;

  std::vector<SkFontStyle> styles;
  for (auto& style : family_info->styles) {
    styles.push_back(
        SkFontStyle(style.weight, style.width, FuchsiaToSkSlant(style.slant)));
  }

  return new FontStyleSet(sk_ref_sp(this), family_info->name,
                          std::move(styles));
}

SkTypeface* FuchsiaFontManager::onMatchFamilyStyle(
    const char familyName[], const SkFontStyle& style) const {
  sk_sp<SkTypeface> typeface = FetchTypeface(familyName, style, nullptr, 0, 0);
  return typeface.release();
}

SkTypeface* FuchsiaFontManager::onMatchFamilyStyleCharacter(
    const char familyName[], const SkFontStyle& style, const char* bcp47[],
    int bcp47_count, SkUnichar character) const {
  sk_sp<SkTypeface> typeface =
      FetchTypeface(kDefaultFontFamily, style, bcp47, bcp47_count, character);
  return typeface.release();
}

SkTypeface* FuchsiaFontManager::onMatchFaceStyle(const SkTypeface*,
                                                 const SkFontStyle&) const {
  DEBUG_CHECK(false, LOG_TAG, "");
  return nullptr;
}

sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromData(sk_sp<SkData>,
                                                     int ttcIndex) const {
  DEBUG_CHECK(false, LOG_TAG, "");
  return nullptr;
}

sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromStreamIndex(
    std::unique_ptr<SkStreamAsset>, int ttcIndex) const {
  DEBUG_CHECK(false, LOG_TAG, "");
  return nullptr;
}

sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromStreamArgs(
    std::unique_ptr<SkStreamAsset>, const SkFontArguments&) const {
  DEBUG_CHECK(false, LOG_TAG, "");
  return nullptr;
}

sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromFile(const char path[],
                                                     int ttcIndex) const {
  DEBUG_CHECK(false, LOG_TAG, "");
  return nullptr;
}

sk_sp<SkTypeface> FuchsiaFontManager::onLegacyMakeTypeface(
    const char familyName[], SkFontStyle) const {
  DEBUG_CHECK(false, LOG_TAG, "");
  return nullptr;
}

sk_sp<SkTypeface> FuchsiaFontManager::FetchTypeface(
    const char family_name[], const SkFontStyle& style, const char* bcp47[],
    int bcp47_count, SkUnichar character, uint32_t flags) const {
  TRACE_DURATION("flutter", "FuchsiaFontManager::FetchTypeface");
  fuchsia::fonts::Request request;
  request.family = family_name;
  request.weight = style.weight();
  request.width = style.width();
  request.slant = SkToFuchsiaSlant(style.slant());
  request.language = BuildLanguageList(bcp47, bcp47_count);
  request.character = character;
  request.flags = flags;

  fuchsia::fonts::ResponsePtr response;
  int err = font_provider_->GetFont(std::move(request), &response);
  if (err != ZX_OK) {
#ifndef NDEBUG
    FX_LOGF(ERROR, LOG_TAG, "Error fetching font from provider [err=%d]. Did "
            "you run Flutter in an environment that has a font manager?", err);
#endif
    return nullptr;
  }

  // The service may return null response if there is no font matching the
  // request.
  if (!response) {
    return nullptr;
  }

  return typeface_cache_->GetOrCreateTypeface(
      response->buffer_id, response->font_index, response->buffer);
}

}  // namespace txt
