<?php
namespace nur\b\io;

use nur\A;

/**
 * Class CacheManager: un gestionnaire de cache permettant de désactiver la mise
 * en cache d'une valeur dans le cadre d'une session.
 *
 * en effet, si on désactive le cache, il doit être réactivé après que la valeur
 * est calculée, pour éviter qu'une valeur soit calculée encore et encore dans
 * une session de travail
 */
class CacheManager {
  function __construct(?array $includes=null, ?array $excludes=null) {
    $this->caches = [];
    $this->defaultCache = true;
    $this->includes = $includes;
    $this->excludes = $excludes;
  }

  /**
   * @var array tableau {id => cache} indiquant si l'élément id doit être mis en
   * cache
   */
  protected array $caches;

  /**
   * @var bool valeur par défaut de cache si la valeur n'est pas trouvée dans
   * $caches
   */
  protected bool $defaultCache;

  /**
   * @var array|null groupes à toujours inclure dans le cache. pour les
   * identifiants de ces groupe, {@link self::shouldCache()} retourne toujours
   * true.
   *
   * $excludes est prioritaire par rapport à $includes
   */
  protected ?array $includes;

  /**
   * @var array|null groupes à exclure de la mise en cache. la mise en cache est
   * toujours calculée pour les identifiants de ces groupes.
   */
  protected ?array $excludes;

  function setNoCache(bool $noCache=true, bool $reset=true): self {
    if ($reset) $this->caches = [];
    $this->defaultCache = !$noCache;
    return $this;
  }

  function shouldCache(string $id, ?string $groupId=null, bool $reset=true): bool {
    if ($groupId !== null) {
      $includes = $this->includes;
      $shouldInclude = $includes !== null && in_array($groupId, $includes);
      $excludes = $this->excludes;
      $shouldExclude = $excludes !== null && in_array($groupId, $excludes);
      if ($shouldInclude && !$shouldExclude) return true;
    }
    $cache = A::get($this->caches, $id, $this->defaultCache);
    $this->caches[$id] = $reset?: $cache;
    return $cache;
  }
}
