/*
 * Copyright © 2020  Google, Inc.
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Google Author(s): Garret Rieger
 */

#ifndef HB_REPACKER_HH
#define HB_REPACKER_HH

#include "hb-open-type.hh"
#include "hb-map.hh"
#include "hb-priority-queue.hh"
#include "hb-serialize.hh"
#include "hb-vector.hh"

/*
 * For a detailed writeup on the overflow resolution algorithm see:
 * docs/repacker.md
 */

struct graph_t
{
  struct vertex_t
  {
    vertex_t () :
        distance (0),
        space (0),
        parents (),
        start (0),
        end (0),
        priority(0) {}

    void fini () {
      obj.fini ();
      parents.fini ();
    }

    hb_serialize_context_t::object_t obj;
    int64_t distance;
    int64_t space;
    hb_vector_t<unsigned> parents;
    unsigned start;
    unsigned end;
    unsigned priority;

    bool is_shared () const
    {
      return parents.length > 1;
    }

    unsigned incoming_edges () const
    {
      return parents.length;
    }

    void remove_parent (unsigned parent_index)
    {
      for (unsigned i = 0; i < parents.length; i++)
      {
        if (parents[i] != parent_index) continue;
        parents.remove (i);
        break;
      }
    }

    void remap_parents (const hb_vector_t<unsigned>& id_map)
    {
      for (unsigned i = 0; i < parents.length; i++)
        parents[i] = id_map[parents[i]];
    }

    void remap_parent (unsigned old_index, unsigned new_index)
    {
      for (unsigned i = 0; i < parents.length; i++)
      {
        if (parents[i] == old_index)
          parents[i] = new_index;
      }
    }

    bool is_leaf () const
    {
      return !obj.links.length;
    }

    void raise_priority ()
    {
      priority++;
    }

    int64_t modified_distance (unsigned order) const
    {
      // TODO(garretrieger): once priority is high enough, should try
      // setting distance = 0 which will force to sort immediately after
      // it's parent where possible.

      int64_t modified_distance =
          hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFF);
      return (modified_distance << 22) | (0x003FFFFF & order);
    }

    int64_t distance_modifier () const
    {
      if (!priority) return 0;
      int64_t table_size = obj.tail - obj.head;
      return -(table_size - table_size / (1 << hb_min(priority, 16u)));
    }
  };

  struct overflow_record_t
  {
    unsigned parent;
    unsigned child;
  };

  /*
   * A topological sorting of an object graph. Ordered
   * in reverse serialization order (first object in the
   * serialization is at the end of the list). This matches
   * the 'packed' object stack used internally in the
   * serializer
   */
  graph_t (const hb_vector_t<hb_serialize_context_t::object_t *>& objects)
      : parents_invalid (true),
        distance_invalid (true),
        positions_invalid (true),
        successful (true)
  {
    num_roots_for_space_.push (1);
    bool removed_nil = false;
    for (unsigned i = 0; i < objects.length; i++)
    {
      // TODO(grieger): check all links point to valid objects.

      // If this graph came from a serialization buffer object 0 is the
      // nil object. We don't need it for our purposes here so drop it.
      if (i == 0 && !objects[i])
      {
        removed_nil = true;
        continue;
      }

      vertex_t* v = vertices_.push ();
      if (check_success (!vertices_.in_error ()))
        v->obj = *objects[i];
      if (!removed_nil) continue;
      for (unsigned i = 0; i < v->obj.links.length; i++)
        // Fix indices to account for removed nil object.
        v->obj.links[i].objidx--;
    }
  }

  ~graph_t ()
  {
    vertices_.fini_deep ();
  }

  bool in_error () const
  {
    return !successful ||
        vertices_.in_error () ||
        num_roots_for_space_.in_error ();
  }

  const vertex_t& root () const
  {
    return vertices_[root_idx ()];
  }

  unsigned root_idx () const
  {
    // Object graphs are in reverse order, the first object is at the end
    // of the vector. Since the graph is topologically sorted it's safe to
    // assume the first object has no incoming edges.
    return vertices_.length - 1;
  }

  const hb_serialize_context_t::object_t& object(unsigned i) const
  {
    return vertices_[i].obj;
  }

  /*
   * serialize graph into the provided serialization buffer.
   */
  void serialize (hb_serialize_context_t* c) const
  {
    c->start_serialize<void> ();
    for (unsigned i = 0; i < vertices_.length; i++) {
      c->push ();

      size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
      char* start = c->allocate_size <char> (size);
      if (!start) return;

      memcpy (start, vertices_[i].obj.head, size);

      for (const auto& link : vertices_[i].obj.links)
        serialize_link (link, start, c);

      // All duplications are already encoded in the graph, so don't
      // enable sharing during packing.
      c->pop_pack (false);
    }
    c->end_serialize ();
  }

  /*
   * Generates a new topological sorting of graph using Kahn's
   * algorithm: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms
   */
  void sort_kahn ()
  {
    positions_invalid = true;

    if (vertices_.length <= 1) {
      // Graph of 1 or less doesn't need sorting.
      return;
    }

    hb_vector_t<unsigned> queue;
    hb_vector_t<vertex_t> sorted_graph;
    if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
    hb_vector_t<unsigned> id_map;
    if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;

    hb_vector_t<unsigned> removed_edges;
    if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
    update_parents ();

    queue.push (root_idx ());
    int new_id = vertices_.length - 1;

    while (!queue.in_error () && queue.length)
    {
      unsigned next_id = queue[0];
      queue.remove (0);

      vertex_t& next = vertices_[next_id];
      sorted_graph[new_id] = next;
      id_map[next_id] = new_id--;

      for (const auto& link : next.obj.links) {
        removed_edges[link.objidx]++;
        if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
          queue.push (link.objidx);
      }
    }

    check_success (!queue.in_error ());
    check_success (!sorted_graph.in_error ());
    if (!check_success (new_id == -1))
      print_orphaned_nodes ();

    remap_all_obj_indices (id_map, &sorted_graph);

    vertices_.swap (sorted_graph);
    sorted_graph.fini_deep ();
  }

  /*
   * Generates a new topological sorting of graph ordered by the shortest
   * distance to each node.
   */
  void sort_shortest_distance ()
  {
    positions_invalid = true;

    if (vertices_.length <= 1) {
      // Graph of 1 or less doesn't need sorting.
      return;
    }

    update_distances ();

    hb_priority_queue_t queue;
    hb_vector_t<vertex_t> sorted_graph;
    if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
    hb_vector_t<unsigned> id_map;
    if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;

    hb_vector_t<unsigned> removed_edges;
    if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
    update_parents ();

    queue.insert (root ().modified_distance (0), root_idx ());
    int new_id = root_idx ();
    unsigned order = 1;
    while (!queue.in_error () && !queue.is_empty ())
    {
      unsigned next_id = queue.pop_minimum().second;

      vertex_t& next = vertices_[next_id];
      sorted_graph[new_id] = next;
      id_map[next_id] = new_id--;

      for (const auto& link : next.obj.links) {
        removed_edges[link.objidx]++;
        if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
          // Add the order that the links were encountered to the priority.
          // This ensures that ties between priorities objects are broken in a consistent
          // way. More specifically this is set up so that if a set of objects have the same
          // distance they'll be added to the topological order in the order that they are
          // referenced from the parent object.
          queue.insert (vertices_[link.objidx].modified_distance (order++),
                        link.objidx);
      }
    }

    check_success (!queue.in_error ());
    check_success (!sorted_graph.in_error ());
    if (!check_success (new_id == -1))
      print_orphaned_nodes ();

    remap_all_obj_indices (id_map, &sorted_graph);

    vertices_.swap (sorted_graph);
    sorted_graph.fini_deep ();
  }

  /*
   * Assign unique space numbers to each connected subgraph of 32 bit offset(s).
   */
  bool assign_32bit_spaces ()
  {
    unsigned root_index = root_idx ();
    hb_set_t visited;
    hb_set_t roots;
    for (unsigned i = 0; i <= root_index; i++)
    {
      for (auto& l : vertices_[i].obj.links)
      {
        if (l.width == 4 && !l.is_signed)
        {
          roots.add (l.objidx);
          find_subgraph (l.objidx, visited);
        }
      }
    }

    // Mark everything not in the subgraphs of 32 bit roots as visited.
    // This prevents 32 bit subgraphs from being connected via nodes not in the 32 bit subgraphs.
    visited.invert ();

    if (!roots) return false;

    while (roots)
    {
      unsigned next = HB_SET_VALUE_INVALID;
      if (!roots.next (&next)) break;

      hb_set_t connected_roots;
      find_connected_nodes (next, roots, visited, connected_roots);
      isolate_subgraph (connected_roots);

      unsigned next_space = this->next_space ();
      num_roots_for_space_.push (0);
      for (unsigned root : connected_roots)
      {
        DEBUG_MSG (SUBSET_REPACK, nullptr, "Subgraph %u gets space %u", root, next_space);
        vertices_[root].space = next_space;
        num_roots_for_space_[next_space] = num_roots_for_space_[next_space] + 1;
        distance_invalid = true;
        positions_invalid = true;
      }

      // TODO(grieger): special case for GSUB/GPOS use extension promotions to move 16 bit space
      //                into the 32 bit space as needed, instead of using isolation.
    }

    return true;
  }

  /*
   * Isolates the subgraph of nodes reachable from root. Any links to nodes in the subgraph
   * that originate from outside of the subgraph will be removed by duplicating the linked to
   * object.
   *
   * Indices stored in roots will be updated if any of the roots are duplicated to new indices.
   */
  bool isolate_subgraph (hb_set_t& roots)
  {
    update_parents ();
    hb_hashmap_t<unsigned, unsigned> subgraph;

    // incoming edges to root_idx should be all 32 bit in length so we don't need to de-dup these
    // set the subgraph incoming edge count to match all of root_idx's incoming edges
    hb_set_t parents;
    for (unsigned root_idx : roots)
    {
      subgraph.set (root_idx, wide_parents (root_idx, parents));
      find_subgraph (root_idx, subgraph);
    }

    unsigned original_root_idx = root_idx ();
    hb_hashmap_t<unsigned, unsigned> index_map;
    bool made_changes = false;
    for (auto entry : subgraph.iter ())
    {
      const auto& node = vertices_[entry.first];
      unsigned subgraph_incoming_edges = entry.second;

      if (subgraph_incoming_edges < node.incoming_edges ())
      {
        // Only  de-dup objects with incoming links from outside the subgraph.
        made_changes = true;
        duplicate_subgraph (entry.first, index_map);
      }
    }

    if (!made_changes)
      return false;

    if (original_root_idx != root_idx ()
        && parents.has (original_root_idx))
    {
      // If the root idx has changed since parents was determined, update root idx in parents
      parents.add (root_idx ());
      parents.del (original_root_idx);
    }

    auto new_subgraph =
        + subgraph.keys ()
        | hb_map([&] (unsigned node_idx) {
          if (index_map.has (node_idx)) return index_map[node_idx];
          return node_idx;
        })
        ;

    remap_obj_indices (index_map, new_subgraph);
    remap_obj_indices (index_map, parents.iter (), true);

    // Update roots set with new indices as needed.
    unsigned next = HB_SET_VALUE_INVALID;
    while (roots.next (&next))
    {
      if (index_map.has (next))
      {
        roots.del (next);
        roots.add (index_map[next]);
      }
    }

    return true;
  }

  void find_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& subgraph)
  {
    for (const auto& link : vertices_[node_idx].obj.links)
    {
      if (subgraph.has (link.objidx))
      {
        subgraph.set (link.objidx, subgraph[link.objidx] + 1);
        continue;
      }
      subgraph.set (link.objidx, 1);
      find_subgraph (link.objidx, subgraph);
    }
  }

  void find_subgraph (unsigned node_idx, hb_set_t& subgraph)
  {
    if (subgraph.has (node_idx)) return;
    subgraph.add (node_idx);
    for (const auto& link : vertices_[node_idx].obj.links)
      find_subgraph (link.objidx, subgraph);
  }

  /*
   * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
   * links. index_map is updated with mappings from old id to new id. If a duplication has already
   * been performed for a given index, then it will be skipped.
   */
  void duplicate_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& index_map)
  {
    if (index_map.has (node_idx))
      return;

    index_map.set (node_idx, duplicate (node_idx));
    for (const auto& l : object (node_idx).links) {
      duplicate_subgraph (l.objidx, index_map);
    }
  }

  /*
   * Creates a copy of node_idx and returns it's new index.
   */
  unsigned duplicate (unsigned node_idx)
  {
    positions_invalid = true;
    distance_invalid = true;

    auto* clone = vertices_.push ();
    auto& child = vertices_[node_idx];
    if (vertices_.in_error ()) {
      return -1;
    }

    clone->obj.head = child.obj.head;
    clone->obj.tail = child.obj.tail;
    clone->distance = child.distance;
    clone->space = child.space;
    clone->parents.reset ();

    unsigned clone_idx = vertices_.length - 2;
    for (const auto& l : child.obj.links)
    {
      clone->obj.links.push (l);
      vertices_[l.objidx].parents.push (clone_idx);
    }

    check_success (!clone->obj.links.in_error ());

    // The last object is the root of the graph, so swap back the root to the end.
    // The root's obj idx does change, however since it's root nothing else refers to it.
    // all other obj idx's will be unaffected.
    vertex_t root = vertices_[vertices_.length - 2];
    vertices_[clone_idx] = *clone;
    vertices_[vertices_.length - 1] = root;

    // Since the root moved, update the parents arrays of all children on the root.
    for (const auto& l : root.obj.links)
      vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());

    return clone_idx;
  }

  /*
   * Creates a copy of child and re-assigns the link from
   * parent to the clone. The copy is a shallow copy, objects
   * linked from child are not duplicated.
   */
  bool duplicate (unsigned parent_idx, unsigned child_idx)
  {
    update_parents ();

    unsigned links_to_child = 0;
    for (const auto& l : vertices_[parent_idx].obj.links)
    {
      if (l.objidx == child_idx) links_to_child++;
    }

    if (vertices_[child_idx].incoming_edges () <= links_to_child)
    {
      // Can't duplicate this node, doing so would orphan the original one as all remaining links
      // to child are from parent.
      DEBUG_MSG (SUBSET_REPACK, nullptr, "  Not duplicating %d => %d",
                 parent_idx, child_idx);
      return false;
    }

    DEBUG_MSG (SUBSET_REPACK, nullptr, "  Duplicating %d => %d",
               parent_idx, child_idx);

    unsigned clone_idx = duplicate (child_idx);
    if (clone_idx == (unsigned) -1) return false;
    // duplicate shifts the root node idx, so if parent_idx was root update it.
    if (parent_idx == clone_idx) parent_idx++;

    auto& parent = vertices_[parent_idx];
    for (unsigned i = 0; i < parent.obj.links.length; i++)
    {
      auto& l = parent.obj.links[i];
      if (l.objidx != child_idx)
        continue;

      reassign_link (l, parent_idx, clone_idx);
    }

    return true;
  }

  /*
   * Raises the sorting priority of all children.
   */
  void raise_childrens_priority (unsigned parent_idx)
  {
    DEBUG_MSG (SUBSET_REPACK, nullptr, "  Raising priority of all children of %d",
               parent_idx);
    // This operation doesn't change ordering until a sort is run, so no need
    // to invalidate positions. It does not change graph structure so no need
    // to update distances or edge counts.
    auto& parent = vertices_[parent_idx].obj;
    for (unsigned i = 0; i < parent.links.length; i++)
      vertices_[parent.links[i].objidx].raise_priority ();
  }

  /*
   * Will any offsets overflow on graph when it's serialized?
   */
  bool will_overflow (hb_vector_t<overflow_record_t>* overflows = nullptr)
  {
    if (overflows) overflows->resize (0);
    update_positions ();

    for (int parent_idx = vertices_.length - 1; parent_idx >= 0; parent_idx--)
    {
      for (const auto& link : vertices_[parent_idx].obj.links)
      {
        int64_t offset = compute_offset (parent_idx, link);
        if (is_valid_offset (offset, link))
          continue;

        if (!overflows) return true;

        overflow_record_t r;
        r.parent = parent_idx;
        r.child = link.objidx;
        overflows->push (r);
      }
    }

    if (!overflows) return false;
    return overflows->length;
  }

  void print_orphaned_nodes ()
  {
    if (!DEBUG_ENABLED(SUBSET_REPACK)) return;

    DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
    parents_invalid = true;
    update_parents();

    for (unsigned i = 0; i < root_idx (); i++)
    {
      const auto& v = vertices_[i];
      if (!v.parents)
        DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i);
    }
  }

  void print_overflows (const hb_vector_t<overflow_record_t>& overflows)
  {
    if (!DEBUG_ENABLED(SUBSET_REPACK)) return;

    update_parents ();
    for (const auto& o : overflows)
    {
      const auto& parent = vertices_[o.parent];
      const auto& child = vertices_[o.child];
      DEBUG_MSG (SUBSET_REPACK, nullptr,
                 "  overflow from "
                 "%4d (%4d in, %4d out, space %2d) => "
                 "%4d (%4d in, %4d out, space %2d)",
                 o.parent,
                 parent.incoming_edges (),
                 parent.obj.links.length,
                 space_for (o.parent),
                 o.child,
                 child.incoming_edges (),
                 child.obj.links.length,
                 space_for (o.child));
    }
  }

  unsigned num_roots_for_space (unsigned space) const
  {
    return num_roots_for_space_[space];
  }

  unsigned next_space () const
  {
    return num_roots_for_space_.length;
  }

  void move_to_new_space (unsigned index)
  {
    auto& node = vertices_[index];
    num_roots_for_space_.push (1);
    num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1;
    node.space = num_roots_for_space_.length - 1;
  }

  unsigned space_for (unsigned index, unsigned* root = nullptr) const
  {
    const auto& node = vertices_[index];
    if (node.space)
    {
      if (root != nullptr)
        *root = index;
      return node.space;
    }

    if (!node.parents)
    {
      if (root)
        *root = index;
      return 0;
    }

    return space_for (node.parents[0], root);
  }

  void err_other_error () { this->successful = false; }

 private:

  /*
   * Returns the numbers of incoming edges that are 32bits wide.
   */
  unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
  {
    unsigned count = 0;
    hb_set_t visited;
    for (unsigned p : vertices_[node_idx].parents)
    {
      if (visited.has (p)) continue;
      visited.add (p);

      for (const auto& l : vertices_[p].obj.links)
      {
        if (l.objidx == node_idx && l.width == 4 && !l.is_signed)
        {
          count++;
          parents.add (p);
        }
      }
    }
    return count;
  }

  bool check_success (bool success)
  { return this->successful && (success || (err_other_error (), false)); }

  /*
   * Creates a map from objid to # of incoming edges.
   */
  void update_parents ()
  {
    if (!parents_invalid) return;

    for (unsigned i = 0; i < vertices_.length; i++)
      vertices_[i].parents.reset ();

    for (unsigned p = 0; p < vertices_.length; p++)
    {
      for (auto& l : vertices_[p].obj.links)
      {
        vertices_[l.objidx].parents.push (p);
      }
    }

    parents_invalid = false;
  }

  /*
   * compute the serialized start and end positions for each vertex.
   */
  void update_positions ()
  {
    if (!positions_invalid) return;

    unsigned current_pos = 0;
    for (int i = root_idx (); i >= 0; i--)
    {
      auto& v = vertices_[i];
      v.start = current_pos;
      current_pos += v.obj.tail - v.obj.head;
      v.end = current_pos;
    }

    positions_invalid = false;
  }

  /*
   * Finds the distance to each object in the graph
   * from the initial node.
   */
  void update_distances ()
  {
    if (!distance_invalid) return;

    // Uses Dijkstra's algorithm to find all of the shortest distances.
    // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
    //
    // Implementation Note:
    // Since our priority queue doesn't support fast priority decreases
    // we instead just add new entries into the queue when a priority changes.
    // Redundant ones are filtered out later on by the visited set.
    // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf
    // for practical performance this is faster then using a more advanced queue
    // (such as a fibonaacci queue) with a fast decrease priority.
    for (unsigned i = 0; i < vertices_.length; i++)
    {
      if (i == vertices_.length - 1)
        vertices_[i].distance = 0;
      else
        vertices_[i].distance = hb_int_max (int64_t);
    }

    hb_priority_queue_t queue;
    queue.insert (0, vertices_.length - 1);

    hb_vector_t<bool> visited;
    visited.resize (vertices_.length);

    while (!queue.in_error () && !queue.is_empty ())
    {
      unsigned next_idx = queue.pop_minimum ().second;
      if (visited[next_idx]) continue;
      const auto& next = vertices_[next_idx];
      int64_t next_distance = vertices_[next_idx].distance;
      visited[next_idx] = true;

      for (const auto& link : next.obj.links)
      {
        if (visited[link.objidx]) continue;

        const auto& child = vertices_[link.objidx].obj;
        int64_t child_weight = (child.tail - child.head) +
                               ((int64_t) 1 << (link.width * 8)) * (vertices_[link.objidx].space + 1);
        int64_t child_distance = next_distance + child_weight;

        if (child_distance < vertices_[link.objidx].distance)
        {
          vertices_[link.objidx].distance = child_distance;
          queue.insert (child_distance, link.objidx);
        }
      }
    }

    check_success (!queue.in_error ());
    if (!check_success (queue.is_empty ()))
    {
      print_orphaned_nodes ();
      return;
    }

    distance_invalid = false;
  }

  int64_t compute_offset (
      unsigned parent_idx,
      const hb_serialize_context_t::object_t::link_t& link) const
  {
    const auto& parent = vertices_[parent_idx];
    const auto& child = vertices_[link.objidx];
    int64_t offset = 0;
    switch ((hb_serialize_context_t::whence_t) link.whence) {
      case hb_serialize_context_t::whence_t::Head:
        offset = child.start - parent.start; break;
      case hb_serialize_context_t::whence_t::Tail:
        offset = child.start - parent.end; break;
      case hb_serialize_context_t::whence_t::Absolute:
        offset = child.start; break;
    }

    assert (offset >= link.bias);
    offset -= link.bias;
    return offset;
  }

  bool is_valid_offset (int64_t offset,
                        const hb_serialize_context_t::object_t::link_t& link) const
  {
    if (link.is_signed)
    {
      if (link.width == 4)
        return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31);
      else
        return offset >= -(1 << 15) && offset < (1 << 15);
    }
    else
    {
      if (link.width == 4)
        return offset >= 0 && offset < ((int64_t) 1 << 32);
      else if (link.width == 3)
        return offset >= 0 && offset < ((int32_t) 1 << 24);
      else
        return offset >= 0 && offset < (1 << 16);
    }
  }

  /*
   * Updates a link in the graph to point to a different object. Corrects the
   * parents vector on the previous and new child nodes.
   */
  void reassign_link (hb_serialize_context_t::object_t::link_t& link,
                      unsigned parent_idx,
                      unsigned new_idx)
  {
    unsigned old_idx = link.objidx;
    link.objidx = new_idx;
    vertices_[old_idx].remove_parent (parent_idx);
    vertices_[new_idx].parents.push (parent_idx);
  }

  /*
   * Updates all objidx's in all links using the provided mapping. Corrects incoming edge counts.
   */
  template<typename Iterator, hb_requires (hb_is_iterator (Iterator))>
  void remap_obj_indices (const hb_hashmap_t<unsigned, unsigned>& id_map,
                          Iterator subgraph,
                          bool only_wide = false)
  {
    if (!id_map) return;
    for (unsigned i : subgraph)
    {
      for (unsigned j = 0; j < vertices_[i].obj.links.length; j++)
      {
        auto& link = vertices_[i].obj.links[j];
        if (!id_map.has (link.objidx)) continue;
        if (only_wide && !(link.width == 4 && !link.is_signed)) continue;

        reassign_link (link, i, id_map[link.objidx]);
      }
    }
  }

  /*
   * Updates all objidx's in all links using the provided mapping.
   */
  void remap_all_obj_indices (const hb_vector_t<unsigned>& id_map,
                              hb_vector_t<vertex_t>* sorted_graph) const
  {
    for (unsigned i = 0; i < sorted_graph->length; i++)
    {
      (*sorted_graph)[i].remap_parents (id_map);
      for (unsigned j = 0; j < (*sorted_graph)[i].obj.links.length; j++)
      {
        auto& link = (*sorted_graph)[i].obj.links[j];
        link.objidx = id_map[link.objidx];
      }
    }
  }

  template <typename O> void
  serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
                          char* head,
                          hb_serialize_context_t* c) const
  {
    OT::Offset<O>* offset = reinterpret_cast<OT::Offset<O>*> (head + link.position);
    *offset = 0;
    c->add_link (*offset,
                 // serializer has an extra nil object at the start of the
                 // object array. So all id's are +1 of what our id's are.
                 link.objidx + 1,
                 (hb_serialize_context_t::whence_t) link.whence,
                 link.bias);
  }

  void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
                 char* head,
                 hb_serialize_context_t* c) const
  {
    switch (link.width)
    {
    case 4:
      if (link.is_signed)
      {
        serialize_link_of_type<OT::HBINT32> (link, head, c);
      } else {
        serialize_link_of_type<OT::HBUINT32> (link, head, c);
      }
      return;
    case 2:
      if (link.is_signed)
      {
        serialize_link_of_type<OT::HBINT16> (link, head, c);
      } else {
        serialize_link_of_type<OT::HBUINT16> (link, head, c);
      }
      return;
    case 3:
      serialize_link_of_type<OT::HBUINT24> (link, head, c);
      return;
    default:
      // Unexpected link width.
      assert (0);
    }
  }

  /*
   * Finds all nodes in targets that are reachable from start_idx, nodes in visited will be skipped.
   * For this search the graph is treated as being undirected.
   *
   * Connected targets will be added to connected and removed from targets. All visited nodes
   * will be added to visited.
   */
  void find_connected_nodes (unsigned start_idx,
                             hb_set_t& targets,
                             hb_set_t& visited,
                             hb_set_t& connected)
  {
    if (visited.has (start_idx)) return;
    visited.add (start_idx);

    if (targets.has (start_idx))
    {
      targets.del (start_idx);
      connected.add (start_idx);
    }

    const auto& v = vertices_[start_idx];

    // Graph is treated as undirected so search children and parents of start_idx
    for (const auto& l : v.obj.links)
      find_connected_nodes (l.objidx, targets, visited, connected);

    for (unsigned p : v.parents)
      find_connected_nodes (p, targets, visited, connected);
  }

 public:
  // TODO(garretrieger): make private, will need to move most of offset overflow code into graph.
  hb_vector_t<vertex_t> vertices_;
 private:
  bool parents_invalid;
  bool distance_invalid;
  bool positions_invalid;
  bool successful;
  hb_vector_t<unsigned> num_roots_for_space_;
};

static bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows,
                                      graph_t& sorted_graph)
{
  for (int i = overflows.length - 1; i >= 0; i--)
  {
    const graph_t::overflow_record_t& r = overflows[i];
    unsigned root = 0;
    unsigned space = sorted_graph.space_for (r.parent, &root);
    if (!space) continue;
    if (sorted_graph.num_roots_for_space (space) <= 1) continue;

    DEBUG_MSG (SUBSET_REPACK, nullptr, "Overflow in space %d moving subgraph %d to space %d.",
               space,
               root,
               sorted_graph.next_space ());

    hb_set_t roots;
    roots.add (root);
    sorted_graph.isolate_subgraph (roots);
    for (unsigned new_root : roots)
      sorted_graph.move_to_new_space (new_root);
    return true;
  }
  return false;
}

static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows,
                                hb_set_t& priority_bumped_parents,
                                graph_t& sorted_graph)
{
  bool resolution_attempted = false;

  // Try resolving the furthest overflows first.
  for (int i = overflows.length - 1; i >= 0; i--)
  {
    const graph_t::overflow_record_t& r = overflows[i];
    const auto& child = sorted_graph.vertices_[r.child];
    if (child.is_shared ())
    {
      // The child object is shared, we may be able to eliminate the overflow
      // by duplicating it.
      if (!sorted_graph.duplicate (r.parent, r.child)) continue;
      return true;
    }

    if (child.is_leaf () && !priority_bumped_parents.has (r.parent))
    {
      // This object is too far from it's parent, attempt to move it closer.
      //
      // TODO(garretrieger): initially limiting this to leaf's since they can be
      //                     moved closer with fewer consequences. However, this can
      //                     likely can be used for non-leafs as well.
      // TODO(garretrieger): add a maximum priority, don't try to raise past this.
      // TODO(garretrieger): also try lowering priority of the parent. Make it
      //                     get placed further up in the ordering, closer to it's children.
      //                     this is probably preferable if the total size of the parent object
      //                     is < then the total size of the children (and the parent can be moved).
      //                     Since in that case moving the parent will cause a smaller increase in
      //                     the length of other offsets.
      sorted_graph.raise_childrens_priority (r.parent);
      priority_bumped_parents.add (r.parent);
      resolution_attempted = true;
      continue;
    }

    // TODO(garretrieger): add additional offset resolution strategies
    // - Promotion to extension lookups.
    // - Table splitting.
  }

  return resolution_attempted;
}

/*
 * Attempts to modify the topological sorting of the provided object graph to
 * eliminate offset overflows in the links between objects of the graph. If a
 * non-overflowing ordering is found the updated graph is serialized it into the
 * provided serialization context.
 *
 * If necessary the structure of the graph may be modified in ways that do not
 * affect the functionality of the graph. For example shared objects may be
 * duplicated.
 *
 * For a detailed writeup describing how the algorithm operates see:
 * docs/repacker.md
 */
inline void
hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed,
                      hb_tag_t table_tag,
                      hb_serialize_context_t* c,
                      unsigned max_rounds = 10) {
  // Kahn sort is ~twice as fast as shortest distance sort and works for many fonts
  // so try it first to save time.
  graph_t sorted_graph (packed);
  sorted_graph.sort_kahn ();
  if (!sorted_graph.will_overflow ())
  {
    sorted_graph.serialize (c);
    return;
  }

  sorted_graph.sort_shortest_distance ();

  if ((table_tag == HB_OT_TAG_GPOS
       ||  table_tag == HB_OT_TAG_GSUB)
      && sorted_graph.will_overflow ())
  {
    DEBUG_MSG (SUBSET_REPACK, nullptr, "Assigning spaces to 32 bit subgraphs.");
    if (sorted_graph.assign_32bit_spaces ())
      sorted_graph.sort_shortest_distance ();
  }

  unsigned round = 0;
  hb_vector_t<graph_t::overflow_record_t> overflows;
  // TODO(garretrieger): select a good limit for max rounds.
  while (!sorted_graph.in_error ()
         && sorted_graph.will_overflow (&overflows)
         && round++ < max_rounds) {
    DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Overflow resolution round %d ===", round);
    sorted_graph.print_overflows (overflows);

    hb_set_t priority_bumped_parents;

    if (!_try_isolating_subgraphs (overflows, sorted_graph))
    {
      if (!_process_overflows (overflows, priority_bumped_parents, sorted_graph))
      {
        DEBUG_MSG (SUBSET_REPACK, nullptr, "No resolution available :(");
        break;
      }
    }

    sorted_graph.sort_shortest_distance ();
  }

  if (sorted_graph.in_error ())
  {
    c->err (HB_SERIALIZE_ERROR_OTHER);
    return;
  }

  if (sorted_graph.will_overflow ())
  {
    c->err (HB_SERIALIZE_ERROR_OFFSET_OVERFLOW);
    DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed.");
    return;
  }
  sorted_graph.serialize (c);
}

#endif /* HB_REPACKER_HH */
