/*
 * Copyright © 2018  Ebrahim Byagowi
 *
 *  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.
 */

#ifndef HB_OT_STAT_TABLE_HH
#define HB_OT_STAT_TABLE_HH

#include "hb-open-type.hh"
#include "hb-ot-layout-common.hh"

/*
 * STAT -- Style Attributes
 * https://docs.microsoft.com/en-us/typography/opentype/spec/stat
 */
#define HB_OT_TAG_STAT HB_TAG('S','T','A','T')


namespace OT {

enum
{
  OLDER_SIBLING_FONT_ATTRIBUTE = 0x0001,	/* If set, this axis value table
						 * provides axis value information
						 * that is applicable to other fonts
						 * within the same font family. This
						 * is used if the other fonts were
						 * released earlier and did not include
						 * information about values for some axis.
						 * If newer versions of the other
						 * fonts include the information
						 * themselves and are present,
						 * then this record is ignored. */
  ELIDABLE_AXIS_VALUE_NAME = 0x0002		/* If set, it indicates that the axis
						 * value represents the “normal” value
						 * for the axis and may be omitted when
						 * composing name strings. */
  // Reserved = 0xFFFC				/* Reserved for future use — set to zero. */
};

static bool axis_value_is_outside_axis_range (hb_tag_t axis_tag, float axis_value,
                                              const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location)
{
  if (!user_axes_location->has (axis_tag))
    return false;

  Triple axis_range = user_axes_location->get (axis_tag);
  return (axis_value < axis_range.minimum || axis_value > axis_range.maximum);
}

struct StatAxisRecord
{
  int cmp (hb_tag_t key) const { return tag.cmp (key); }

  hb_ot_name_id_t get_name_id () const { return nameID; }

  hb_tag_t get_axis_tag () const { return tag; }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this)));
  }

  protected:
  Tag		tag;		/* A tag identifying the axis of design variation. */
  NameID	nameID;		/* The name ID for entries in the 'name' table that
				 * provide a display string for this axis. */
  HBUINT16	ordering;	/* A value that applications can use to determine
				 * primary sorting of face names, or for ordering
				 * of descriptors when composing family or face names. */
  public:
  DEFINE_SIZE_STATIC (8);
};

struct AxisValueFormat1
{
  unsigned int get_axis_index () const { return axisIndex; }
  float get_value ()             const { return value.to_float (); }

  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }

  hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
  {
    unsigned axis_idx = get_axis_index ();
    return axis_records[axis_idx].get_axis_tag ();
  }

  bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
                        const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
  {
    hb_tag_t axis_tag = get_axis_tag (axis_records);
    float axis_value = get_value ();

    return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location);
  }

  bool subset (hb_subset_context_t *c,
               const hb_array_t<const StatAxisRecord> axis_records) const
  {
    TRACE_SUBSET (this);
    const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location;

    if (keep_axis_value (axis_records, user_axes_location))
      return_trace (c->serializer->embed (this));

    return_trace (false);
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this));
  }

  protected:
  HBUINT16	format;		/* Format identifier — set to 1. */
  HBUINT16	axisIndex;	/* Zero-base index into the axis record array
				 * identifying the axis of design variation
				 * to which the axis value record applies.
				 * Must be less than designAxisCount. */
  HBUINT16	flags;		/* Flags — see below for details. */
  NameID	valueNameID;	/* The name ID for entries in the 'name' table
				 * that provide a display string for this
				 * attribute value. */
  F16DOT16	value;		/* A numeric value for this attribute value. */
  public:
  DEFINE_SIZE_STATIC (12);
};

struct AxisValueFormat2
{
  unsigned int get_axis_index () const { return axisIndex; }
  float get_value ()             const { return nominalValue.to_float (); }

  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }

  hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
  {
    unsigned axis_idx = get_axis_index ();
    return axis_records[axis_idx].get_axis_tag ();
  }

  bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
                        const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
  {
    hb_tag_t axis_tag = get_axis_tag (axis_records);
    float axis_value = get_value ();

    return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location);
  }

  bool subset (hb_subset_context_t *c,
               const hb_array_t<const StatAxisRecord> axis_records) const
  {
    TRACE_SUBSET (this);
    const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location;

    if (keep_axis_value (axis_records, user_axes_location))
      return_trace (c->serializer->embed (this));

    return_trace (false);
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this));
  }

  protected:
  HBUINT16	format;		/* Format identifier — set to 2. */
  HBUINT16	axisIndex;	/* Zero-base index into the axis record array
				 * identifying the axis of design variation
				 * to which the axis value record applies.
				 * Must be less than designAxisCount. */
  HBUINT16	flags;		/* Flags — see below for details. */
  NameID	valueNameID;	/* The name ID for entries in the 'name' table
				 * that provide a display string for this
				 * attribute value. */
  F16DOT16	nominalValue;	/* A numeric value for this attribute value. */
  F16DOT16	rangeMinValue;	/* The minimum value for a range associated
				 * with the specified name ID. */
  F16DOT16	rangeMaxValue;	/* The maximum value for a range associated
				 * with the specified name ID. */
  public:
  DEFINE_SIZE_STATIC (20);
};

struct AxisValueFormat3
{
  unsigned int get_axis_index () const { return axisIndex; }
  float get_value ()             const { return value.to_float (); }

  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }

  hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
  {
    unsigned axis_idx = get_axis_index ();
    return axis_records[axis_idx].get_axis_tag ();
  }

  bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
                        const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
  {
    hb_tag_t axis_tag = get_axis_tag (axis_records);
    float axis_value = get_value ();

    return !axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location);
  }

  bool subset (hb_subset_context_t *c,
               const hb_array_t<const StatAxisRecord> axis_records) const
  {
    TRACE_SUBSET (this);
    const hb_hashmap_t<hb_tag_t, Triple>* user_axes_location = &c->plan->user_axes_location;

    if (keep_axis_value (axis_records, user_axes_location))
      return_trace (c->serializer->embed (this));

    return_trace (false);
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this));
  }

  protected:
  HBUINT16	format;		/* Format identifier — set to 3. */
  HBUINT16	axisIndex;	/* Zero-base index into the axis record array
				 * identifying the axis of design variation
				 * to which the axis value record applies.
				 * Must be less than designAxisCount. */
  HBUINT16	flags;		/* Flags — see below for details. */
  NameID	valueNameID;	/* The name ID for entries in the 'name' table
				 * that provide a display string for this
				 * attribute value. */
  F16DOT16	value;		/* A numeric value for this attribute value. */
  F16DOT16	linkedValue;	/* The numeric value for a style-linked mapping
				 * from this value. */
  public:
  DEFINE_SIZE_STATIC (16);
};

struct AxisValueRecord
{
  unsigned int get_axis_index () const { return axisIndex; }
  float get_value ()             const { return value.to_float (); }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (c->check_struct (this));
  }

  protected:
  HBUINT16	axisIndex;	/* Zero-base index into the axis record array
				 * identifying the axis to which this value
				 * applies. Must be less than designAxisCount. */
  F16DOT16	value;		/* A numeric value for this attribute value. */
  public:
  DEFINE_SIZE_STATIC (6);
};

struct AxisValueFormat4
{
  const AxisValueRecord &get_axis_record (unsigned int axis_index) const
  { return axisValues.as_array (axisCount)[axis_index]; }

  bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
                        const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
  {
    hb_array_t<const AxisValueRecord> axis_value_records = axisValues.as_array (axisCount);

    for (const auto& rec : axis_value_records)
    {
      unsigned axis_idx = rec.get_axis_index ();
      float axis_value = rec.get_value ();
      hb_tag_t axis_tag = axis_records[axis_idx].get_axis_tag ();

      if (axis_value_is_outside_axis_range (axis_tag, axis_value, user_axes_location))
        return false;
    }

    return true;
  }

  bool subset (hb_subset_context_t *c,
               const hb_array_t<const StatAxisRecord> axis_records) const
  {
    TRACE_SUBSET (this);
    const hb_hashmap_t<hb_tag_t, Triple> *user_axes_location = &c->plan->user_axes_location;
    if (!keep_axis_value (axis_records, user_axes_location))
      return_trace (false);

    unsigned total_size = min_size + axisCount * AxisValueRecord::static_size;
    auto *out = c->serializer->allocate_size<AxisValueFormat4> (total_size);
    if (unlikely (!out)) return_trace (false);
    hb_memcpy (out, this, total_size);
    return_trace (true);
  }

  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
                          axisValues.sanitize (c, axisCount)));
  }

  protected:
  HBUINT16	format;		/* Format identifier — set to 4. */
  HBUINT16	axisCount;	/* The total number of axes contributing to
				 * this axis-values combination. */
  HBUINT16	flags;		/* Flags — see below for details. */
  NameID	valueNameID;	/* The name ID for entries in the 'name' table
				 * that provide a display string for this
				 * attribute value. */
  UnsizedArrayOf<AxisValueRecord>
		axisValues;	/* Array of AxisValue records that provide the
				 * combination of axis values, one for each
				 * contributing axis. */
  public:
  DEFINE_SIZE_ARRAY (8, axisValues);
};

struct AxisValue
{
  bool get_value (unsigned int axis_index) const
  {
    switch (u.format)
    {
    case 1: return u.format1.get_value ();
    case 2: return u.format2.get_value ();
    case 3: return u.format3.get_value ();
    case 4: return u.format4.get_axis_record (axis_index).get_value ();
    default:return 0;
    }
  }

  unsigned int get_axis_index () const
  {
    switch (u.format)
    {
    case 1: return u.format1.get_axis_index ();
    case 2: return u.format2.get_axis_index ();
    case 3: return u.format3.get_axis_index ();
    /* case 4: Makes more sense for variable fonts which are handled by fvar in hb-style */
    default:return -1;
    }
  }

  hb_ot_name_id_t get_value_name_id () const
  {
    switch (u.format)
    {
    case 1: return u.format1.get_value_name_id ();
    case 2: return u.format2.get_value_name_id ();
    case 3: return u.format3.get_value_name_id ();
    case 4: return u.format4.get_value_name_id ();
    default:return HB_OT_NAME_ID_INVALID;
    }
  }

  template <typename context_t, typename ...Ts>
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
  {
    if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
    TRACE_DISPATCH (this, u.format);
    switch (u.format) {
    case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
    case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
    case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
    case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
    default:return_trace (c->default_return_value ());
    }
  }

  bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
                        hb_hashmap_t<hb_tag_t, Triple> *user_axes_location) const
  {
    switch (u.format)
    {
    case 1: return u.format1.keep_axis_value (axis_records, user_axes_location);
    case 2: return u.format2.keep_axis_value (axis_records, user_axes_location);
    case 3: return u.format3.keep_axis_value (axis_records, user_axes_location);
    case 4: return u.format4.keep_axis_value (axis_records, user_axes_location);
    default:return false;
    }
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    if (unlikely (!c->check_struct (this)))
      return_trace (false);

    switch (u.format)
    {
    case 1: return_trace (u.format1.sanitize (c));
    case 2: return_trace (u.format2.sanitize (c));
    case 3: return_trace (u.format3.sanitize (c));
    case 4: return_trace (u.format4.sanitize (c));
    default:return_trace (true);
    }
  }

  protected:
  union
  {
  HBUINT16		format;
  AxisValueFormat1	format1;
  AxisValueFormat2	format2;
  AxisValueFormat3	format3;
  AxisValueFormat4	format4;
  } u;
  public:
  DEFINE_SIZE_UNION (2, format);
};

struct AxisValueOffsetArray: UnsizedArrayOf<Offset16To<AxisValue>>
{
  bool subset (hb_subset_context_t *c,
               unsigned axisValueCount,
               unsigned& count,
               const hb_array_t<const StatAxisRecord> axis_records) const
  {
    TRACE_SUBSET (this);

    auto axisValueOffsets = as_array (axisValueCount);
    count = 0;
    for (const auto& offset : axisValueOffsets)
    {
      if (!offset) continue;
      auto o_snap = c->serializer->snapshot ();
      auto *o = c->serializer->embed (offset);
      if (!o) return_trace (false);
      if (!o->serialize_subset (c, offset, this, axis_records))
      {
        c->serializer->revert (o_snap);
        continue;
      }
      count++;
    }

    return_trace (count);
  }
};

struct STAT
{
  static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT;

  bool has_data () const { return version.to_int (); }

  bool get_value (hb_tag_t tag, float *value) const
  {
    unsigned int axis_index;
    if (!get_design_axes ().lfind (tag, &axis_index)) return false;

    hb_array_t<const Offset16To<AxisValue>> axis_values = get_axis_value_offsets ();
    for (unsigned int i = 0; i < axis_values.length; i++)
    {
      const AxisValue& axis_value = this+axis_values[i];
      if (axis_value.get_axis_index () == axis_index)
      {
	if (value)
	  *value = axis_value.get_value (axis_index);
	return true;
      }
    }
    return false;
  }

  unsigned get_design_axis_count () const { return designAxisCount; }

  hb_ot_name_id_t get_axis_record_name_id (unsigned axis_record_index) const
  {
    if (unlikely (axis_record_index >= designAxisCount)) return HB_OT_NAME_ID_INVALID;
    const StatAxisRecord &axis_record = get_design_axes ()[axis_record_index];
    return axis_record.get_name_id ();
  }

  unsigned get_axis_value_count () const { return axisValueCount; }

  hb_ot_name_id_t get_axis_value_name_id (unsigned axis_value_index) const
  {
    if (unlikely (axis_value_index >= axisValueCount)) return HB_OT_NAME_ID_INVALID;
    const AxisValue &axis_value = (this + get_axis_value_offsets ()[axis_value_index]);
    return axis_value.get_value_name_id ();
  }

  void collect_name_ids (hb_hashmap_t<hb_tag_t, Triple> *user_axes_location,
                         hb_set_t *nameids_to_retain /* OUT */) const
  {
    if (!has_data ()) return;

    + get_design_axes ()
    | hb_map (&StatAxisRecord::get_name_id)
    | hb_sink (nameids_to_retain)
    ;

    auto designAxes = get_design_axes ();

    + get_axis_value_offsets ()
    | hb_map (hb_add (&(this + offsetToAxisValueOffsets)))
    | hb_filter ([&] (const AxisValue& _)
                 { return _.keep_axis_value (designAxes, user_axes_location); })
    | hb_map (&AxisValue::get_value_name_id)
    | hb_sink (nameids_to_retain)
    ;

    nameids_to_retain->add (elidedFallbackNameID);
  }

  bool subset (hb_subset_context_t *c) const
  {
    TRACE_SUBSET (this);
    STAT *out = c->serializer->embed (this);
    if (unlikely (!out)) return_trace (false);

    auto designAxes = get_design_axes ();
    for (unsigned i = 0; i < (unsigned)designAxisCount; i++)
      if (unlikely (!c->serializer->embed (designAxes[i])))
          return_trace (false);

    if (designAxisCount)
      c->serializer->check_assign (out->designAxesOffset, this->get_size (),
                                   HB_SERIALIZE_ERROR_INT_OVERFLOW);

    unsigned count = 0;
    out->offsetToAxisValueOffsets.serialize_subset (c, offsetToAxisValueOffsets, this,
                                                    axisValueCount, count, designAxes);
    return_trace (c->serializer->check_assign (out->axisValueCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
  }

  bool sanitize (hb_sanitize_context_t *c) const
  {
    TRACE_SANITIZE (this);
    return_trace (likely (c->check_struct (this) &&
			  version.major == 1 &&
			  version.minor > 0 &&
			  designAxesOffset.sanitize (c, this, designAxisCount) &&
			  offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
  }

  protected:
  hb_array_t<const StatAxisRecord> const get_design_axes () const
  { return (this+designAxesOffset).as_array (designAxisCount); }

  hb_array_t<const Offset16To<AxisValue>> const get_axis_value_offsets () const
  { return (this+offsetToAxisValueOffsets).as_array (axisValueCount); }


  protected:
  FixedVersion<>version;	/* Version of the stat table
				 * initially set to 0x00010002u */
  HBUINT16	designAxisSize;	/* The size in bytes of each axis record. */
  HBUINT16	designAxisCount;/* The number of design axis records. In a
				 * font with an 'fvar' table, this value must be
				 * greater than or equal to the axisCount value
				 * in the 'fvar' table. In all fonts, must
				 * be greater than zero if axisValueCount
				 * is greater than zero. */
  NNOffset32To<UnsizedArrayOf<StatAxisRecord>>
		designAxesOffset;
				/* Offset in bytes from the beginning of
				 * the STAT table to the start of the design
				 * axes array. If designAxisCount is zero,
				 * set to zero; if designAxisCount is greater
				 * than zero, must be greater than zero. */
  HBUINT16	axisValueCount;	/* The number of axis value tables. */
  NNOffset32To<AxisValueOffsetArray>
		offsetToAxisValueOffsets;
				/* Offset in bytes from the beginning of
				 * the STAT table to the start of the design
				 * axes value offsets array. If axisValueCount
				 * is zero, set to zero; if axisValueCount is
				 * greater than zero, must be greater than zero. */
  NameID	elidedFallbackNameID;
				/* Name ID used as fallback when projection of
				 * names into a particular font model produces
				 * a subfamily name containing only elidable
				 * elements. */
  public:
  DEFINE_SIZE_STATIC (20);
};


} /* namespace OT */


#endif /* HB_OT_STAT_TABLE_HH */
