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

use ArrayAccess;
use nur\sery\cl;

/**
 * Class KeyAccess: accès à une valeur d'une clé dans un tableau
 */
class KeyAccess extends AbstractAccess {
  function __construct(&$dest, $key, ?array $params=null) {
    $this->dest =& $dest;
    $this->key = $key;
    $this->allowNull = $params["allow_null"] ?? true;
    $this->allowFalse = $params["allow_false"] ?? false;
    $this->allowEmpty = $params["allow_empty"] ?? true;
  }

  /** @var array|ArrayAccess */
  protected $dest;

  function reset(&$dest): self {
    $this->dest =& $dest;
    return $this;
  }

  /** @var int|string */
  protected $key;

  protected bool $allowNull;

  protected bool $allowFalse;

  protected bool $allowEmpty;

  function exists(): bool {
    $key = $this->key;
    if ($key === null) return false;
    return cl::has($this->dest, $key);
  }

  function available(): bool {
    if (!$this->exists()) return false;
    $value = cl::get($this->dest, $this->key);
    if ($value === null) return $this->allowNull;
    if ($value === false) return $this->allowFalse;
    if ($value === "") return $this->allowEmpty;
    return true;
  }

  function get($default=null) {
    if ($this->key === null) return $default;
    $value = cl::get($this->dest, $this->key, $default);
    if ($value === null && !$this->allowNull) return $default;
    if ($value === false && !$this->allowFalse) return $default;
    if ($value === "" && !$this->allowEmpty) return $default;
    return $value;
  }

  function set($value): void {
    if ($this->key === null) return;
    cl::set($this->dest, $this->key, $value);
  }

  function del(): void {
    if ($this->key === null) return;
    cl::del($this->dest, $this->key);
  }
}
