<?php
namespace nur\mapper\base\capacitor;

/**
 * Interface ICapacitor: objet qui permet d'accumuler des données pour les
 * fournir en une seule fois au moment voulu
 */
interface ICapacitor {
  const KEY_SCHEMA = [
    "name" => ["key", null, "nom de la clé", "required" => true],
    "primary" => ["bool", false, "est-ce une clé primaire?"],
    "reverse" => ["?bool", null, "sens du tri par défaut"],
  ];

  /**
   * spécifier les clés à traquer lors du chargement d'une donnée.
   *
   * si une clé est marquée comme primaire, alors les doublons éventuels sont
   * supprimés au fur et à mesure du chargement.
   */
  function setKeys(array $keys, ?string $channel=null): void;

  const SORT_SCHEMA = [
    "name" => ["key", null, "nom de la clé", "required" => true],
    "reverse" => ["?bool", null, "sens du tri"],
  ];

  /**
   * trier les données selon les clés spécifiées. si $keys===null, alors toutes
   * les clés définies au préalable avec {@link setKeys()} sont utilisées.
   *
   * $keys ne doit mentionner que des clés déclarées avec {@link setKeys()}
   */
  function sort(?array $keys=null, ?string $channel=null): void;

  /**
   * charger l'accumulateur avec un élément.
   *
   * Dans le cas où $item === null, le comportement est particulier:
   * - Si aucune clé primaire n'a été définie, l'élément est systématiquement
   * chargé
   * - Si une clé primaire a été définie, l'élément est ignoré, sauf si
   * $pkvalues est spécifiée. Dans ce cas, $pkvalues est utilisé comme clé
   * primaire
   */
  function charge($item, ?string $channel=null, $pkvalues=null): void;

  /** méthode de convenance pour charger l'accumulateur avec plusieurs éléments */
  function chargeAll(iterable $items, ?string $channel=null): void;

  /**
   * obtenir un élément à partir de sa clé primaire. une clé primaire doit avoir
   * été définie au préalable avec {@link setKeys()}
   *
   * si aucune clé primaire n'a été définie, alors le seul moyen d'atteindre un
   * élément est par son index
   */
  function getItem($pkvalues, ?string $channel=null, $default=null);

  /** décharger l'accumulateur en une seule fois */
  function discharge(?string $channel=null, bool $remove=true): iterable;
}
