<?php
namespace nur\mapper\base\oobd;

use nur\A;
use nur\mapper\base\mark_utils;

trait TOobdManager {
  /** @var IOobdManager instance partagée */
  protected $sharedOobdManager;

  function getSharedOobdManager(): ?IOobdManager {
    return $this->sharedOobdManager;
  }

  function setSharedOobdManager(IOobdManager $sharedOobdManager): self {
    $this->sharedOobdManager = $sharedOobdManager;
    return $this;
  }

  function ensureSharedOobdManager(): void {
    if ($this->sharedOobdManager === null) {
      $this->sharedOobdManager = new OobdManager();
    }
  }

  protected $oobdValues;

  protected function _hasOobdValue(string $name): bool {
    return A::has($this->oobdValues, $name);
  }

  protected function _getOobdValue(string $name, $default) {
    return A::get($this->oobdValues, $name, $default);
  }

  protected function _setOobdValue(string $name, $value): void {
    $this->oobdValues[$name] = $value;
  }

  protected function _unsetOobdValue(string $name): void {
    unset($this->oobdValues[$name]);
  }

  function hasOvalue(string $name): bool {
    if ($this->_hasOobdValue($name)) {
      return true;
    } elseif ($this->sharedOobdManager !== null
      && $this->sharedOobdManager->hasOvalue($name)) {
      return true;
    }
    return false;
  }

  function getOvalue(string $name, $default=null) {
    if ($this->_hasOobdValue($name)) {
      return $this->_getOobdValue($name, $default);
    } elseif ($this->sharedOobdManager !== null
      && $this->sharedOobdManager->hasOvalue($name)) {
      return $this->sharedOobdManager->getOvalue($name, $default);
    }
    return null;
  }

  function setOvalue(string $name, $value, bool $shared=true) {
    if ($shared && $this->sharedOobdManager !== null) {
      return $this->sharedOobdManager->setOvalue($name, $value, false);
    } else {
      $oldValue = $this->_getOobdValue($name, null);
      if (is_bool($value) && $oldValue === true) {
        $value = $oldValue;
      } else {
        $this->_setOobdValue($name, $value);
      }
      return $value;
    }
  }

  function incOvalue(string $name, bool $shared=true): int {
    if ($shared && $this->sharedOobdManager !== null) {
      return $this->sharedOobdManager->incOvalue($name, false);
    } else {
      $value = intval($this->_getOobdValue($name, 0)) + 1;
      $this->_setOobdValue($name, $value);
      return $value;
    }
  }

  function decOvalue(string $name, bool $shared=true): int {
    if ($shared && $this->sharedOobdManager !== null) {
      return $this->sharedOobdManager->incOvalue($name, false);
    } else {
      $value = intval($this->_getOobdValue($name, 0)) - 1;
      $this->_setOobdValue($name, $value);
      return $value;
    }
  }

  function resetOvalue(string $name, $value=null, bool $shared=true) {
    if ($shared && $this->sharedOobdManager !== null) {
      return $this->sharedOobdManager->resetOvalue($name, $value, false);
    } else {
      if ($value === null) $this->_unsetOobdValue($name);
      else $this->_setOobdValue($name, $value);
      return $value;
    }
  }

  function setUseKeysForItemMarked(?array $keys, ?string $prefix=null): void {
    mark_utils::set_use_keys_for_item_marked($this, $keys, $prefix);
  }

  function setItemMarked($item, ?string $prefix=null, bool $shared=true): void {
    mark_utils::set_item_marked($this, $item, $prefix, $shared);
  }

  function isItemMarked($item, ?string $prefix=null): bool {
    return mark_utils::is_item_marked($this, $item, $prefix);
  }
}