/*
 * 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 <zx/vmar.h>
#include <unordered_map>

#include "lib/fsl/vmo/sized_vmo.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/memory/weak_ptr.h"
#include "third_party/icu/source/common/unicode/uchar.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;
  std::function<void()> release_proc;

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

void ReleaseSkData(const void* buffer, void* context) {
  auto skdata_context = reinterpret_cast<ReleaseSkDataContext*>(context);
  FXL_DCHECK(skdata_context);
  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,
                                   std::function<void()> release_proc) {
  if (!fsl::SizedVmo::IsSizeValid(data.vmo, data.size) ||
      data.size > std::numeric_limits<size_t>::max()) {
    return nullptr;
  }
  uint64_t size = data.size;
  uintptr_t buffer = 0;
  zx_status_t 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, 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) {
  FXL_DCHECK(bcp47 != nullptr || bcp47_count == 0);
  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() : weak_factory_(this) {}
  ~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;

 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);
    }
  };

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

  // 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, SkData*> buffer_cache_;

  // Must be last.
  mutable fxl::WeakPtrFactory<TypefaceCache> weak_factory_;

  FXL_DISALLOW_COPY_AND_ASSIGN(TypefaceCache);
};

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;
  FXL_DCHECK(was_found);
}

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);
  }
  auto weak_this = weak_factory_.GetWeakPtr();
  auto data = MakeSkDataFromBuffer(buffer, buffer_id, [weak_this, buffer_id]() {
    if (weak_this) {
      weak_this->OnSkDataDeleted(buffer_id);
    }
  });
  if (!data) {
    return nullptr;
  }
  buffer_cache_[buffer_id] = data.get();
  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 {
    FXL_DCHECK(index >= 0 && index < static_cast<int>(styles_.size()));
    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 {
    FXL_DCHECK(index >= 0 && index < static_cast<int>(styles_.size()));

    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_;

  FXL_DISALLOW_COPY_AND_ASSIGN(FontStyleSet);
};

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

FuchsiaFontManager::~FuchsiaFontManager() = default;

int FuchsiaFontManager::onCountFamilies() const {
  FXL_DCHECK(false);
  return 0;
}

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

SkFontStyleSet* FuchsiaFontManager::onCreateStyleSet(int index) const {
  FXL_DCHECK(false);
  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) {
    FXL_DLOG(ERROR) << "Error fetching family from provider [err=" << err
                    << "]. Did you run Flutter in an environment that"
                    << " has a font manager? ";
    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 {
  FXL_DCHECK(false);
  return nullptr;
}

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

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

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

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

sk_sp<SkTypeface> FuchsiaFontManager::onLegacyMakeTypeface(
    const char familyName[], SkFontStyle) const {
  FXL_DCHECK(false);
  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 {
  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) {
    FXL_DLOG(ERROR) << "Error fetching font from provider [err=" << err
                    << "]. Did you run Flutter in an environment that"
                    << " has a font manager? ";
    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
