/*
 * Copyright © 2022  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 GRAPH_SERIALIZE_HH
#define GRAPH_SERIALIZE_HH

namespace graph {

struct overflow_record_t
{
  unsigned parent;
  unsigned child;

  bool operator != (const overflow_record_t o) const
  { return !(*this == o); }

  inline bool operator == (const overflow_record_t& o) const
  {
    return parent == o.parent &&
        child == o.child;
  }

  inline uint32_t hash () const
  {
    uint32_t current = 0;
    current = current * 31 + hb_hash (parent);
    current = current * 31 + hb_hash (child);
    return current;
  }
};

inline
int64_t compute_offset (
    const graph_t& graph,
    unsigned parent_idx,
    const hb_serialize_context_t::object_t::link_t& link)
{
  const auto& parent = graph.vertices_[parent_idx];
  const auto& child = graph.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;
}

inline
bool is_valid_offset (int64_t offset,
                      const hb_serialize_context_t::object_t::link_t& link)
{
  if (unlikely (!link.width))
    // Virtual links can't overflow.
    return link.is_signed || offset >= 0;

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

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

  hb_hashmap_t<overflow_record_t*, bool> record_set;
  const auto& vertices = graph.vertices_;
  for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--)
  {
    // Don't need to check virtual links for overflow
    for (const auto& link : vertices.arrayZ[parent_idx].obj.real_links)
    {
      int64_t offset = compute_offset (graph, parent_idx, link);
      if (likely (is_valid_offset (offset, link)))
        continue;

      if (!overflows) return true;

      overflow_record_t r;
      r.parent = parent_idx;
      r.child = link.objidx;
      if (record_set.has(&r)) continue; // don't keep duplicate overflows.

      overflows->push (r);
      record_set.set(&r, true);
    }
  }

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

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

  graph.update_parents ();
  int limit = 10;
  for (const auto& o : overflows)
  {
    if (!limit--) break;
    const auto& parent = graph.vertices_[o.parent];
    const auto& child = graph.vertices_[o.child];
    DEBUG_MSG (SUBSET_REPACK, nullptr,
               "  overflow from "
               "%4u (%4u in, %4u out, space %2u) => "
               "%4u (%4u in, %4u out, space %2u)",
               o.parent,
               parent.incoming_edges (),
               parent.obj.real_links.length + parent.obj.virtual_links.length,
               graph.space_for (o.parent),
               o.child,
               child.incoming_edges (),
               child.obj.real_links.length + child.obj.virtual_links.length,
               graph.space_for (o.child));
  }
  if (overflows.length > 10) {
    DEBUG_MSG (SUBSET_REPACK, nullptr, "  ... plus %u more overflows.", overflows.length - 10);
  }
}

template <typename O> inline void
serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
                        char* head,
                        unsigned size,
                        hb_serialize_context_t* c)
{
  assert(link.position + link.width <= size);

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

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

/*
 * serialize graph into the provided serialization buffer.
 */
inline hb_blob_t* serialize (const graph_t& graph)
{
  hb_vector_t<char> buffer;
  size_t size = graph.total_size_in_bytes ();

  if (!size) return hb_blob_get_empty ();

  if (!buffer.alloc (size)) {
    DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer.");
    return nullptr;
  }
  hb_serialize_context_t c((void *) buffer, size);

  c.start_serialize<void> ();
  const auto& vertices = graph.vertices_;
  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) {
      DEBUG_MSG (SUBSET_REPACK, nullptr, "Buffer out of space.");
      return nullptr;
    }

    hb_memcpy (start, vertices[i].obj.head, size);

    // Only real links needs to be serialized.
    for (const auto& link : vertices[i].obj.real_links)
      serialize_link (link, start, size, &c);

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

  if (c.in_error ()) {
    DEBUG_MSG (SUBSET_REPACK, nullptr, "Error during serialization. Err flag: %d",
               c.errors);
    return nullptr;
  }

  return c.copy_blob ();
}

} // namespace graph

#endif // GRAPH_SERIALIZE_HH
