/*
 * 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
 */

#include "graph.hh"
#include "../OT/Layout/Common/Coverage.hh"

#ifndef GRAPH_COVERAGE_GRAPH_HH
#define GRAPH_COVERAGE_GRAPH_HH

namespace graph {

struct CoverageFormat1 : public OT::Layout::Common::CoverageFormat1_3<SmallTypes>
{
  bool sanitize (graph_t::vertex_t& vertex) const
  {
    int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
    constexpr unsigned min_size = OT::Layout::Common::CoverageFormat1_3<SmallTypes>::min_size;
    if (vertex_len < min_size) return false;
    return vertex_len >= min_size + glyphArray.get_size () - glyphArray.len.get_size ();
  }
};

struct CoverageFormat2 : public OT::Layout::Common::CoverageFormat2_4<SmallTypes>
{
  bool sanitize (graph_t::vertex_t& vertex) const
  {
    int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
    constexpr unsigned min_size = OT::Layout::Common::CoverageFormat2_4<SmallTypes>::min_size;
    if (vertex_len < min_size) return false;
    return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
  }
};

struct Coverage : public OT::Layout::Common::Coverage
{
  static Coverage* clone_coverage (gsubgpos_graph_context_t& c,
                                   unsigned coverage_id,
                                   unsigned new_parent_id,
                                   unsigned link_position,
                                   unsigned start, unsigned end)

  {
    unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
    auto& coverage_v = c.graph.vertices_[coverage_id];
    Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
    if (!coverage_table || !coverage_table->sanitize (coverage_v))
      return nullptr;

    auto new_coverage =
        + hb_zip (coverage_table->iter (), hb_range ())
        | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
          return p.second >= start && p.second < end;
        })
        | hb_map_retains_sorting (hb_first)
        ;

    return add_coverage (c, new_parent_id, link_position, new_coverage, coverage_size);
  }

  template<typename It>
  static Coverage* add_coverage (gsubgpos_graph_context_t& c,
                                 unsigned parent_id,
                                 unsigned link_position,
                                 It glyphs,
                                 unsigned max_size)
  {
    unsigned coverage_prime_id = c.graph.new_node (nullptr, nullptr);
    auto& coverage_prime_vertex = c.graph.vertices_[coverage_prime_id];
    if (!make_coverage (c, glyphs, coverage_prime_id, max_size))
      return nullptr;

    auto* coverage_link = c.graph.vertices_[parent_id].obj.real_links.push ();
    coverage_link->width = SmallTypes::size;
    coverage_link->objidx = coverage_prime_id;
    coverage_link->position = link_position;
    coverage_prime_vertex.parents.push (parent_id);

    return (Coverage*) coverage_prime_vertex.obj.head;
  }

  template<typename It>
  static bool make_coverage (gsubgpos_graph_context_t& c,
                             It glyphs,
                             unsigned dest_obj,
                             unsigned max_size)
  {
    char* buffer = (char*) hb_calloc (1, max_size);
    hb_serialize_context_t serializer (buffer, max_size);
    OT::Layout::Common::Coverage_serialize (&serializer, glyphs);
    serializer.end_serialize ();
    if (serializer.in_error ())
    {
      hb_free (buffer);
      return false;
    }

    hb_bytes_t coverage_copy = serializer.copy_bytes ();
    c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer.

    auto& obj = c.graph.vertices_[dest_obj].obj;
    obj.head = (char *) coverage_copy.arrayZ;
    obj.tail = obj.head + coverage_copy.length;

    hb_free (buffer);
    return true;
  }

  bool sanitize (graph_t::vertex_t& vertex) const
  {
    int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
    if (vertex_len < OT::Layout::Common::Coverage::min_size) return false;
    switch (u.format)
    {
    case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
    case 2: return ((CoverageFormat2*)this)->sanitize (vertex);
#ifndef HB_NO_BEYOND_64K
    // Not currently supported
    case 3:
    case 4:
#endif
    default: return false;
    }
  }
};


}

#endif  // GRAPH_COVERAGE_GRAPH_HH
