<?php
/**
 * @copyright (c) Kufer Software GmbH, Loisachstrasse 4, D-84453 Mühldorf
 */

namespace Kufer\Web\Classes\Scripting3;

class ExprFunctionCall extends Expr
{
  
  public const BUILTIN_FUNCTIONS = array(
    'add', 'sub', 'mul', 'mult', 'div', 'trim', 'callfn', 'value',
    'round', 'ceil', 'floor', 'true', 'false', 'render',
  );

  public const BUILTIN_FUNCTIONS_ARGCOUNTS = array(
    'value' => array(-1),
    'callfn' => array(-1),
    'trim' => array(-1),
    'add' => array(2),
    'sub' => array(2),
    'mult' => array(2),
    'div' => array(2),
    'round' => array(1),
    'ceil' => array(1),
    'floor' => array(1),
    'true' => array(0),
    'false' => array(0),
    );

  
  public $fnname;

  
  public $variables;

  public function __construct(string $pFnname, array $pVariables)
  {
    parent::__construct();

    $this->fnname = $pFnname;
    $this->variables = $pVariables;
  }

  public function toString(): string
  {
    return '{%:' . $this->fnname . \implode(':', \array_map(function(\Kufer\Web\Classes\Scripting3\Expr $e): string { return $e->toString(); }, $this->variables)) . '%}';
  }

  public function toPHP(bool $isleaf, ParserHelper $phpcode, array $fnvars): string
  {
    $phpvarresult = array_map(function($e) use ($phpcode, $fnvars) {
      return $e->toPHP(false, $phpcode, $fnvars);
    }, $this->variables);

    if (\in_array($this->fnname, static::BUILTIN_FUNCTIONS)) {
      $result = '\\Kufer\\Web\\Classes\\Scripting3\\ExprFunctionCall::builtin_fn_' . $this->fnname . '('
          . ParserHelper::STD_VARS;

      if (!empty($phpvarresult)) {
        $result .= ', ' . \implode(', ', $phpvarresult);
      }

      $result .= ')';
      if ($isleaf) {
        $result = '$result.=' . $result . ";\n";
      }

      return $result;
    }

    $phpfnname = '(' . $phpcode->createFunctionName($this->fnname, count($this->variables)) . ')(';

    $result = '';

    $result .= '' . $phpfnname . ParserHelper::STD_VARS;
    if (count($phpvarresult) > 0) {
      $result .= ',' . implode(',', $phpvarresult);
    }
    $result .= ')';

    if ($isleaf) {
      $result = '$result.=' . $result . ";\n";
    }

    return $result;
  }

  public static function builtin_fn_add($thisObject, $functions, $stack, $export, $varstore, $var0, $var1)
  {
    return $var0 + $var1;
  }

  public static function builtin_fn_sub($thisObject, $functions, $stack, $export, $varstore, $var0, $var1)
  {
    return $var0 - $var1;
  }

  public static function builtin_fn_mul($thisObject, $functions, $stack, $export, $varstore, $var0, $var1)
  {
    return $var0 * $var1;
  }

  public static function builtin_fn_mult($thisObject, $functions, $stack, $export, $varstore, $var0, $var1)
  {
    return static::builtin_fn_mul($thisObject, $functions, $stack, $export, $varstore, $var0, $var1);
  }

  public static function builtin_fn_div($thisObject, $functions, $stack, $export, $varstore, $var0, $var1)
  {
    return $var0 / $var1;
  }

  public static function builtin_fn_trim($thisObject, $functions, $stack, $export, $varstore, $arg0, ...$args)
  {
    return \trim($arg0) . ((new \Kufer\Web\Classes\Stream\ArrayStream($args))
      ->map('\\trim')
      ->reduce(\FunctionOperations::concat(), ''));
  }

  public static function builtin_fn_callfn($thisObject, $functions, $stack, $export, $varstore, $arg0, ...$args)
  {
    return ($thisObject->{'__c' . strval(\count($args)) . '_' . $arg0})(
      $thisObject,
      $functions,
      $stack,
      $export,
      $varstore,
      ...$args
    );
  }

  public static function builtin_fn_value($thisObject, $functions, $stack, $export, $varstore, $arg0, ...$args)
  {
    $variableName = \trim($arg0) . ((new \Kufer\Web\Classes\Stream\ArrayStream($args))
      ->map('\\trim')
      ->reduce(\FunctionOperations::concat(), ''));

    return $varstore->getVarValue($variableName, $export);
  }

  public static function builtin_fn_round($thisObject, $functions, $stack, $export, $varstore, $arg0)
  {
    return \intval(\round($arg0));
  }

  public static function builtin_fn_floor($thisObject, $functions, $stack, $export, $varstore, $arg0)
  {
    return \intval(\floor($arg0));
  }

  public static function builtin_fn_ceil($thisObject, $functions, $stack, $export, $varstore, $arg0)
  {
    return \intval(\ceil($arg0));
  }

  public static function builtin_fn_true($thisObject, $functions, $stack, $export, $varstore)
  {
    return '1';
  }

  public static function builtin_fn_false($thisObject, $functions, $stack, $export, $varstore)
  {
    return '';
  }

  public static function builtin_fn_ktrender($thisObject, $functions, $stack, $export, $varstore, $arg0)
  {
    $sightPath = \FSOperations::path(BASEDIR, 'kufertools', 'settings');
    $userPath = \FSOperations::path($sightPath, 'user', 'layout', 'template', $arg0);
    if (!\file_exists($userPath)) {
      $userPath = \FSOperations::path($sightPath, 'sys', 'layout', 'template', $arg0);
    }

    $sightApi = new \Kufer\KuferTools\Utils\Sight();
    $sight = $sightApi->getSightFromFilePath($userPath, $arg0, function() use ($userPath) {
      return \Kufer\KuferTools\Basis\View\ViewSight::readTemplateFileContent($userPath);
    });
  }
}