<?php
namespace nur\sery\php;

use ArrayAccess;
use nur\sery\A;
use nur\sery\cl;

/**
 * Class akey: accéder aux valeurs d'un tableau
 *
 * @see valx
 */
class akey {
  /** obtenir la valeur d'une clé */
  static final function get($array, $key, $default=null) {
    if ($array instanceof ArrayAccess) {
      if ($array->offsetExists($key)) return $array->offsetGet($key);
      else return $default;
    } else {
      if (!is_array($array)) $array = cl::with($array);
      return cl::get($array, $key, $default);
    }
  }

  /** spécifier la valeur d'une clé */
  static final function set(&$array, $key, $value) {
    if ($array instanceof ArrayAccess) {
      $array->offsetSet($key, $value);
    } else {
      cl::set($array, $key, $value);
    }
    return $value;
  }

  /** initialiser $dest avec les valeurs de $values */
  static final function set_values(&$array, ?array $values): void {
    if ($values === null) return;
    foreach ($values as $key => $value) {
      self::set($array, $key, $value);
    }
  }

  /** incrémenter la valeur de la clé */
  static final function inc(&$array, $key): int {
    if ($array instanceof ArrayAccess) {
      $value = (int)$array->offsetGet($key);
      $array->offsetSet($key, ++$value);
      return $value;
    } else {
      A::ensure_array($array);
      $value = (int)cl::get($array, $key);
      return $array[$key] = ++$value;
    }
  }

  /** décrémenter la valeur de la clé */
  static final function dec(&$array, $key, bool $allow_negative=false): int {
    if ($array instanceof ArrayAccess) {
      $value = (int)$array->offsetGet($key);
      if ($allow_negative || $value > 0) $array->offsetSet($key, --$value);
      return $value;
    } else {
      A::ensure_array($array);
      $value = (int)cl::get($array, $key);
      if ($allow_negative || $value > 0) $array[$key] = --$value;
      return $value;
    }
  }

  /**
   * fusionner $merge dans la valeur de la clé, qui est d'abord transformé en
   * tableau si nécessaire
   */
  static final function merge(&$array, $key, $merge): void {
    if ($array instanceof ArrayAccess) {
      $value = $array->offsetGet($key);
      $value = cl::merge($value, $merge);
      $array->offsetSet($key, $value);
    } else {
      A::ensure_array($array);
      $array[$key] = cl::merge($array[$key], $merge);
    }
  }

  /**
   * ajouter $value à la valeur de la clé, qui est d'abord transformé en
   * tableau si nécessaire
   */
  static final function append(&$array, $key, $value): void {
    if ($array instanceof ArrayAccess) {
      $value = $array->offsetGet($key);
      cl::set($value, null, $value);
      $array->offsetSet($key, $value);
    } else {
      A::ensure_array($array);
      cl::set($array[$key], null, $value);
    }
  }
}
