<?php
namespace nur\data\expr;

use nur\A;
use nur\b\coll\BaseArray;
use nur\b\ValueException;
use nur\func;
use nur\md;

/**
 * Class GenericExpr: une expression générique, utilisée par défaut
 */
class GenericExpr extends BaseArray implements IExpr {
  static final function with($expr, ?string $key=null): IExpr {
    if ($expr instanceof IExpr) return $expr;
    return new GenericExpr($expr, $key);
  }

  function __construct($data=null, ?string $key=null) {
    md::ensure_schema($data, static::SCHEMA, null, false);
    A::replace_z($data, "name", $key);
    A::replace_z_indirect($data, "name", "value");
    A::replace_z_indirect($data, "title", "name");
    parent::__construct($data);
  }

  function getValue(): ?string {
    return $this->data["value"];
  }

  function getName(): string {
    return $this->data["name"];
  }

  function getTitle(): string {
    return $this->data["title"];
  }

  public function eval(IContext $context) {
    $expr = $this->getValue();
    if (func::is_static($expr) || func::is_method($expr)) {
      return $context->callMethod($expr);
    } elseif (is_string($expr)) {
      $prefix = substr($expr, 0, 1);
      if ($prefix == "*") {
        # session
        return $context->getSession(substr($expr, 1));
      } elseif ($prefix == "+") {
        # config
        return $context->getConfig(substr($expr, 1));
      }
      # valeur à récupérer du contexte
      return $context->getValue($expr);
    }
    throw ValueException::unexpected_type(["string", "callable"], $expr);
  }
}