<?php
namespace nur\mapper\item;

use nur\A;
use nur\b\params\Tparametrable;
use nur\mapper\base\Mapper;

/**
 * Class Seq2AssocMapper: transformer un flux de tableaux séquentiels en
 * tableaux associatifs
 *
 * --autogen-properties-and-methods--
 * @method bool|null getParseKeys()
 * @method array|null getKeys()
 * @method bool|null setParseKeys(?bool $value)
 * @method array|null setKeys(?array $value)
 */
class Seq2AssocMapper extends Mapper {
  use Tparametrable;

  const PARAMETRABLE_PARAMS_SCHEMA = [
    "parse_keys" => ["?bool", null, "faut-il analyser le premier élément du flux pour calculer la liste des clés en entrée?"],
    "keys" => ["?array", null, "liste et ordre des clés en entrée"],
  ];

  /**
   * @var ?bool faut-il analyser le premier élément du flux pour calculer la
   * liste des clés en entrée? null signifie que la valeur est dynamique: elle
   * vaut ($keys === null)
   *
   * Si ce champ est vrai, le premier élément est toujours consommé. cependant,
   * la liste des champs n'est analysée que si elle n'a pas été spécifiée au
   * préalable avec {@link setKeys()}
   */
  protected $ppParseKeys;

  /**
   * @var array liste des champs en entrée dans l'ordre. si cette valeur n'est
   * pas spécifiée, elle est calculée à partir du premier élément du flux.
   */
  protected $ppKeys;

  function _checkKeys(array $keys): bool {
    $parseKeys = $this->ppParseKeys;
    $setParseKeys = $parseKeys !== null;
    if ($parseKeys === null) $parseKeys = $this->ppKeys === null;
    if ($parseKeys) {
      if ($this->ppKeys === null) $this->ppKeys = $keys;
      if ($setParseKeys) $this->ppParseKeys = false;
      return true;
    }
    return false;
  }

  function _mapValues(array $values): array {
    $keys = $this->ppKeys;
    if ($keys === null) return $values;
    $row = [];
    $index = 0;
    foreach ($keys as $key) {
      $row[$key] = A::get($values, $index++, false);
    }
    return $row;
  }

  function mapper($item) {
    $values = A::with($item);
    if ($this->_checkKeys($values)) return $this->mapToNone();
    return $this->_mapValues($values);
  }

  #############################################################################
  const _AUTOGEN_CONSTS = [
    "" => [self::class, "_autogen_consts"],
  ];
  const _AUTOGEN_LITERALS = /*autogen*/[
    [
      \nur\b\params\parametrable_utils::class,
      '\\nur\\b\\params\\parametrable_utils::class',
    ],
    [
      self::PARAMETRABLE_PARAMS_SCHEMA,
      'self::PARAMETRABLE_PARAMS_SCHEMA',
    ],
  ];
  const _AUTOGEN_METHODS = /*autogen*/[
    [
      \nur\b\params\parametrable_utils::class,
      '_autogen_methods_getters',
      self::PARAMETRABLE_PARAMS_SCHEMA,
      null,
    ],
    [
      \nur\b\params\parametrable_utils::class,
      '_autogen_methods_setters',
      self::PARAMETRABLE_PARAMS_SCHEMA,
      null,
    ],
  ];
  const _AUTO_GETTERS = /*autogen*/[
    'getParseKeys' => 'parse_keys',
    'getKeys' => 'keys',
  ];
  const _AUTO_SETTERS = /*autogen*/[
    'setParseKeys' => 'parse_keys',
    'setKeys' => 'keys',
  ];
  #--autogen-dynamic--
}
