<?php
namespace nulib\php\access;

use nulib\cl;

/**
 * Class FormAccess: accès à une valeur de $_POST puis $_GET, dans cet ordre
 */
class FormAccess extends AbstractAccess {
  const ALLOW_EMPTY = false;

  function __construct($key, ?array $params=null) {
    parent::__construct($params);
    $this->key = $key;
  }

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

  protected function _exists(array $first, ?array $second=null): bool {
    $key = $this->key;
    if ($key === null) return true;
    if (cl::phas($first, $key)) return true;
    return $second !== null && cl::phas($second, $key);
  }

  function exists(): bool {
    return $this->_exists($_POST, $_GET);
  }

  protected function _available(array $first, ?array $second=null): bool {
    $key = $this->key;
    if ($key === null) return true;
    if (cl::phas($first, $key)) {
      return $this->allowEmpty || cl::pget($first, $key) !== "";
    } elseif ($second !== null && cl::phas($second, $key)) {
      return $this->allowEmpty || cl::pget($second, $key) !== "";
    } else {
      return false;
    }
  }

  public function available(): bool {
    return $this->_available($_POST, $_GET);
  }

  protected function _get($default, array $first, ?array $second=null) {
    $key = $this->key;
    if ($key === null) return cl::merge($first, $second);
    if (cl::phas($first, $key)) {
      $value = cl::pget($first, $key);
      if ($value !== "" || $this->allowEmpty) return $value;
    } elseif ($second !== null && cl::phas($second, $key)) {
      $value = cl::pget($second, $key);
      if ($value !== "" || $this->allowEmpty) return $value;
    }
    return $default;
  }

  function get($default=null) {
    return $this->_get($default, $_POST, $_GET);
  }

  function _set($value, array &$first, ?array &$second=null): void {
    $key = $this->key;
    if ($key === null) {
      # interdire la modification de la destination
      return;
    }
    if ($second !== null && !cl::phas($first, $key) && cl::phas($second, $key)) {
      cl::pset($second, $key, $value);
    } else {
      cl::pset($first, $key, $value);
    }
  }

  function set($value): void {
    $this->_set($value, $_POST, $_GET);
  }

  function _del(array &$first, ?array &$second=null): void {
    $key = $this->key;
    if ($key === null) {
      # interdire la modification de la destination
      return;
    }
    if ($second !== null && !cl::phas($first, $key) && cl::phas($second, $key)) {
      cl::pdel($second, $key);
    } else {
      cl::pdel($first, $key);
    }
  }

  function del(): void {
    $this->_del($_POST, $_GET);
  }

  function addKey($key): self {
    if ($key === null) return $this;
    if ($this->key !== null) $key = cl::merge($this->key, $key);
    return new static($key, [
      "allow_empty" => $this->allowEmpty
    ]);
  }
}
