<?php
namespace nur\sery\wip\schema;

use IteratorAggregate;
use nur\sery\wip\schema\_assoc\AssocResult;
use nur\sery\wip\schema\_list\ListResult;
use nur\sery\wip\schema\_scalar\ScalarResult;

/**
 * Class Result: résultat de l'analyse ou de la normalisation d'une valeur
 *
 * @property bool $resultAvailable le résultat est-il disponible?
 * @property bool $present la valeur existe-t-elle?
 * @property bool $available si la valeur existe, est-elle disponible?
 * @property bool $null si la valeur est disponible, est-elle nulle?
 * @property bool $valid si la valeur est disponible, est-elle valide?
 * @property bool $normalized si la valeur est valide, est-elle normalisée?
 * @property string|null $messageKey clé de message si la valeur n'est pas valide
 * @property string|null $message message si la valeur n'est pas valide
 * @property string|null $origValue valeur originale avant extraction et analyse
 * @property mixed|null $normalizedValue la valeur normalisée si elle est
 *  disponible, null sinon. ce champ est utilisé comme optimisation si la valeur
 *  normalisée a déjà été calculée
 */
abstract class Result implements IteratorAggregate {
  const KEYS = [
    "resultAvailable",
    "present", "available", "null", "valid", "normalized",
    "messageKey", "message",
    "origValue", "normalizedValue",
  ];

  function __construct() {
    $this->reset();
  }

  function isAssoc(?AssocResult &$result=null): bool { return false; }
  function isList(?ListResult &$result=null): bool { return false; }
  function isScalar(?ScalarResult &$result=null): bool { return false; }

  /**
   * Obtenir la liste des clés valides pour les valeurs accessibles via cet
   * objet
   */
  abstract function getKeys(): array;

  /**
   * sélectionner le résultat associé à la clé spécifiée
   *
   * @param string|int|null $key
   * @return Result $this
   */
  abstract function select($key): Result;

  function getIterator() {
    foreach ($this->getKeys() as $key) {
      yield $key => $this->select($key);
    }
    $this->select(null);
  }

  /** réinitialiser tous les objets résultats accessibles via cet objet */
  abstract function reset(): void;
}
