// 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.
    if (!hb_ot_var_has_data(face) || hb_ot_var_get_axis_count(face) == 0) {
      // we can only drop GSUB/GPOS/GDEF for non variable fonts, they may be
      // needed for variable fonts (guessing we need to keep all of these, but
      // in Material Symbols Icon variable fonts if we drop the GSUB table (they
      // do not have GPOS/DEF) then the Fill=1,Weight=100 variation is rendered
      // incorrect. (and other variations are probably less noticibly
      // incorrect))
      hb_set_add(hb_subset_input_set(input, HB_SUBSET_SETS_DROP_TABLE_TAG),
                 HB_TAG('G', 'S', 'U', 'B'));
      hb_set_add(hb_subset_input_set(input, HB_SUBSET_SETS_DROP_TABLE_TAG),
                 HB_TAG('G', 'P', 'O', 'S'));
      hb_set_add(hb_subset_input_set(input, HB_SUBSET_SETS_DROP_TABLE_TAG),
                 HB_TAG('G', 'D', 'E', 'F'));
    }
    return HarfbuzzWrappers::HbFacePtr(hb_subset_or_fail(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;
}
