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

use nur\sery\wip\php\access\IAccess;
use nur\sery\wip\php\access\KeyAccess;
use nur\sery\wip\php\access\ValueAccess;

/**
 * Class Input: accès à une valeur
 *
 * cette implémentation lit depuis et écrit dans une référence
 */
class Input {
  const ALLOW_EMPTY = true;

  function __construct(&$dest=null, ?array $params=null) {
    $this->dest =& $dest;
    $this->allowEmpty = $params["allow_empty"] ?? static::ALLOW_EMPTY;
  }

  /** @var mixed */
  protected $dest;

  /**
   * @var bool comment considérer une chaine vide: "" si allowEmpty, null sinon
   */
  protected $allowEmpty;

  protected ?ValueAccess $valueAccess = null;
  protected ?array $keyAccess = null;

  protected function access($key): IAccess {
    if ($key === null) {
      return $this->valueAccess ??= new ValueAccess($this->dest, [
        "allow_null" => true,
        "allow_empty" => $this->allowEmpty,
      ]);
    } else {
      return $this->keyAccess[$key] ??= new KeyAccess($this->dest, $key, [
        "allow_empty" => $this->allowEmpty,
      ]);
    }
  }

  /** tester si la valeur existe sans tenir compte de $allowEmpty */
  function isPresent($key=null): bool {
    return $this->access($key)->exists();
  }

  /** tester si la valeur est disponible en tenant compte de $allowEmpty */
  function isAvailable($key=null): bool {
    return $this->access($key)->available();
  }

  function get($key=null) {
    return $this->access($key)->get();
  }

  function set($value, $key=null): void {
    $this->access($key)->set($value);
  }

  function unset($key=null): void {
    $this->access($key)->del();
  }
}