// 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 <hb-subset.h>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <limits>
#include <set>
#include <string>

#include "hb_wrappers.h"

hb_codepoint_t ParseCodepoint(const std::string& arg) {
  uint64_t value = 0;
  // Check for \u123, u123, otherwise let strtoul work it out.
  if (arg[0] == 'u') {
    value = strtoul(arg.c_str() + 1, nullptr, 16);
  } else if (arg[0] == '\\' && arg[1] == 'u') {
    value = strtoul(arg.c_str() + 2, nullptr, 16);
  } else {
    value = strtoul(arg.c_str(), nullptr, 0);
  }
  if (value == 0 || value > std::numeric_limits<hb_codepoint_t>::max()) {
    std::cerr << "The value '" << arg << "' (" << value
              << ") could not be parsed as a valid unicode codepoint; aborting."
              << std::endl;
    exit(-1);
  }
  return value;
}

void Usage() {
  std::cout << "Usage:" << std::endl;
  std::cout << "font-subset <output.ttf> <input.ttf>" << std::endl;
  std::cout << std::endl;
  std::cout << "The output.ttf file will be overwritten if it exists already "
               "and the subsetting operation succeeds."
            << std::endl;
  std::cout << "Codepoints should be specified on stdin, separated by spaces, "
               "and must be input as decimal numbers (123), hexadecimal "
               "numbers (0x7B), or unicode hexadecimal characters (\\u7B)."
            << std::endl;
  std::cout << "Input terminates with a newline." << std::endl;
  std::cout
      << "This program will de-duplicate codepoints if the same codepoint is "
         "specified multiple times, e.g. '123 123' will be treated as '123'."
      << std::endl;
}

template <typename...>
using void_t = void;
template <typename T, typename = void>
struct HarfBuzzSubset {
  // This is the HarfBuzz 3.0 interface.
  static HarfbuzzWrappers::HbFacePtr Make(hb_face_t* face, T input) {
    // The prior version of harfbuzz automatically dropped layout tables,
    // but in the new version they are kept by default. So re-add them to the
    // drop list to retain the same behaviour.
    hb_set_add(hb_subset_input_drop_tables_set(input),
               HB_TAG('G', 'S', 'U', 'B'));
    hb_set_add(hb_subset_input_drop_tables_set(input),
               HB_TAG('G', 'P', 'O', 'S'));
    hb_set_add(hb_subset_input_drop_tables_set(input),
               HB_TAG('G', 'D', 'E', 'F'));

    return HarfbuzzWrappers::HbFacePtr(hb_subset_or_fail(face, input));
  }
};
template <typename T>
struct HarfBuzzSubset<T,
                      void_t<decltype(hb_subset(std::declval<hb_face_t*>(),
                                                std::declval<T>()))>> {
  // This is the HarfBuzz 2.0 (non-public) interface, used if it exists.
  // This code should be removed as soon as all users are migrated to the newer
  // API.
  static HarfbuzzWrappers::HbFacePtr Make(hb_face_t* face, T input) {
    return HarfbuzzWrappers::HbFacePtr(hb_subset(face, input));
  }
};

int main(int argc, char** argv) {
  if (argc != 3) {
    Usage();
    return -1;
  }
  std::string output_file_path(argv[1]);
  std::string input_file_path(argv[2]);
  std::cout << "Using output file: " << output_file_path << std::endl;
  std::cout << "Using source file: " << input_file_path << std::endl;

  HarfbuzzWrappers::HbBlobPtr font_blob(
      hb_blob_create_from_file(input_file_path.c_str()));
  if (!hb_blob_get_length(font_blob.get())) {
    std::cerr << "Failed to load input font " << input_file_path
              << "; aborting. This error indicates that the font is invalid or "
                 "the current version of Harfbuzz is unable to process it."
              << std::endl;
    return -1;
  }

  HarfbuzzWrappers::HbFacePtr font_face(hb_face_create(font_blob.get(), 0));
  if (font_face.get() == hb_face_get_empty()) {
    std::cerr << "Failed to load input font face " << input_file_path
              << "; aborting. This error indicates that the font is invalid or "
                 "the current version of Harfbuzz is unable to process it."
              << std::endl;
    return -1;
  }

  HarfbuzzWrappers::HbSubsetInputPtr input(hb_subset_input_create_or_fail());
  {
    hb_set_t* desired_codepoints = hb_subset_input_unicode_set(input.get());
    HarfbuzzWrappers::HbSetPtr actual_codepoints(hb_set_create());
    hb_face_collect_unicodes(font_face.get(), actual_codepoints.get());
    std::string raw_codepoint;
    while (std::cin >> raw_codepoint) {
      auto codepoint = ParseCodepoint(raw_codepoint);
      if (!codepoint) {
        std::cerr << "Invalid codepoint for " << raw_codepoint << "; exiting."
                  << std::endl;
        return -1;
      }
      if (!hb_set_has(actual_codepoints.get(), codepoint)) {
        std::cerr << "Codepoint " << raw_codepoint
                  << " not found in font, aborting." << std::endl;
        return -1;
      }
      hb_set_add(desired_codepoints, codepoint);
    }
    if (hb_set_is_empty(desired_codepoints)) {
      std::cerr << "No codepoints specified, exiting." << std::endl;
      return -1;
    }
  }

  HarfbuzzWrappers::HbFacePtr new_face =
      HarfBuzzSubset<hb_subset_input_t*>::Make(font_face.get(), input.get());

  if (!new_face || new_face.get() == hb_face_get_empty()) {
    std::cerr
        << "Failed to subset font; aborting. This error normally indicates "
           "the current version of Harfbuzz is unable to process it."
        << std::endl;
    return -1;
  }

  HarfbuzzWrappers::HbBlobPtr result(hb_face_reference_blob(new_face.get()));
  if (!hb_blob_get_length(result.get())) {
    std::cerr << "Failed get new font bytes; aborting. This error may indicate "
                 "low availability of memory or a bug in Harfbuzz."
              << std::endl;
    return -1;
  }

  unsigned int data_length;
  const char* data = hb_blob_get_data(result.get(), &data_length);

  std::ofstream output_font_file;
  output_font_file.open(output_file_path,
                        std::ios::out | std::ios::trunc | std::ios::binary);
  if (!output_font_file.is_open()) {
    std::cerr << "Failed to open output file '" << output_file_path
              << "'. The parent directory may not exist, or the user does not "
                 "have permission to create this file."
              << std::endl;
    return -1;
  }
  output_font_file.write(data, data_length);
  output_font_file.flush();
  output_font_file.close();

  std::cout << "Wrote " << data_length << " bytes to " << output_file_path
            << std::endl;
  return 0;
}
