#include <cassert>
#include <cstring>
#include <thread>
#include <condition_variable>
#include <vector>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "hb-subset.h"

enum operation_t
{
  subset_codepoints,
  subset_glyphs
};

#define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"

struct test_input_t
{
  const char *font_path;
  const unsigned max_subset_size;
} default_tests[] =
{
  {SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf", 4000},
  {SUBSET_FONT_BASE_PATH "Amiri-Regular.ttf", 4000},
  {SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf", 1000},
  {SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf", 1000},
  {SUBSET_FONT_BASE_PATH "Mplus1p-Regular.ttf", 10000},
  {SUBSET_FONT_BASE_PATH "SourceHanSans-Regular_subset.otf", 10000},
  {SUBSET_FONT_BASE_PATH "SourceSansPro-Regular.otf", 2000},
};


static test_input_t *tests = default_tests;
static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);


// https://en.cppreference.com/w/cpp/thread/condition_variable/wait
static std::condition_variable cv;
static std::mutex cv_m;
static bool ready = false;

static unsigned num_repetitions = 1;
static unsigned num_threads = 3;

static void AddCodepoints(const hb_set_t* codepoints_in_font,
                          unsigned subset_size,
                          hb_subset_input_t* input)
{
  auto *unicodes = hb_subset_input_unicode_set (input);
  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
  for (unsigned i = 0; i < subset_size; i++) {
    if (!hb_set_next (codepoints_in_font, &cp)) return;
    hb_set_add (unicodes, cp);
  }
}

static void AddGlyphs(unsigned num_glyphs_in_font,
               unsigned subset_size,
               hb_subset_input_t* input)
{
  auto *glyphs = hb_subset_input_glyph_set (input);
  for (unsigned i = 0; i < subset_size && i < num_glyphs_in_font; i++) {
    hb_set_add (glyphs, i);
  }
}

static void subset (operation_t operation,
                    const test_input_t &test_input,
                    hb_face_t *face)
{
  // Wait till all threads are ready.
  {
    std::unique_lock<std::mutex> lk (cv_m);
    cv.wait(lk, [] {return ready;});
  }

  unsigned subset_size = test_input.max_subset_size;

  hb_subset_input_t* input = hb_subset_input_create_or_fail ();
  assert (input);

  switch (operation)
  {
    case subset_codepoints:
    {
      hb_set_t* all_codepoints = hb_set_create ();
      hb_face_collect_unicodes (face, all_codepoints);
      AddCodepoints(all_codepoints, subset_size, input);
      hb_set_destroy (all_codepoints);
    }
    break;

    case subset_glyphs:
    {
      unsigned num_glyphs = hb_face_get_glyph_count (face);
      AddGlyphs(num_glyphs, subset_size, input);
    }
    break;
  }

  for (unsigned i = 0; i < num_repetitions; i++)
  {
    hb_face_t* subset = hb_subset_or_fail (face, input);
    assert (subset);
    hb_face_destroy (subset);
  }

  hb_subset_input_destroy (input);
}

static void test_operation (operation_t operation,
                            const char *operation_name,
                            const test_input_t &test_input)
{
  char name[1024] = "subset";
  const char *p;
  strcat (name, "/");
  p = strrchr (test_input.font_path, '/');
  strcat (name, p ? p + 1 : test_input.font_path);
  strcat (name, "/");
  strcat (name, operation_name);

  printf ("Testing %s\n", name);

  hb_face_t *face;
  {
    hb_blob_t *blob = hb_blob_create_from_file_or_fail (test_input.font_path);
    assert (blob);
    face = hb_face_create (blob, 0);
    hb_blob_destroy (blob);
  }

  std::vector<std::thread> threads;
  for (unsigned i = 0; i < num_threads; i++)
    threads.push_back (std::thread (subset, operation, test_input, face));

  {
    std::unique_lock<std::mutex> lk (cv_m);
    ready = true;
  }
  cv.notify_all();

  for (unsigned i = 0; i < num_threads; i++)
    threads[i].join ();

  hb_face_destroy (face);
}

int main(int argc, char** argv)
{
  if (argc > 1)
    num_threads = atoi (argv[1]);
  if (argc > 2)
    num_repetitions = atoi (argv[2]);

  if (argc > 4)
  {
    num_tests = argc - 3;
    tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
    for (unsigned i = 0; i < num_tests; i++)
    {
      tests[i].font_path = argv[3 + i];
    }
  }

  printf ("Num threads %u; num repetitions %u\n", num_threads, num_repetitions);
  for (unsigned i = 0; i < num_tests; i++)
  {
    auto& test_input = tests[i];
    test_operation (subset_codepoints, "codepoints", test_input);
    test_operation (subset_glyphs, "glyphs", test_input);
  }

  if (tests != default_tests)
    free (tests);
}
