<?php
namespace nur\v;

use nur\c;
use nur\co;
use nur\str;
use nur\v\html5\Html5LayoutManager;
use nur\v\model\ILayoutManager;

/**
 * Class ly: gestion globale de la mise en page
 */
class ly {
  const MANAGER_CLASS = Html5LayoutManager::class;

  protected static $manager_class;

  /**
   * spécifier la classe à utiliser pour instancier le gestionnaire de
   * mise en page
   *
   * cette méthode *doit* être appelée avant d'appeler la méthode
   * {@link manager()}
   */
  static final function set_manager_class(string $manager_class) {
    self::$manager_class = $manager_class;
  }

  /** @var ILayoutManager */
  protected static $manager;

  static final function set_manager(ILayoutManager $manager) {
    self::$manager = $manager;
  }

  /** obtenir l'instance globale de gestionnaire de mise en page */
  static final function manager(): ILayoutManager {
    if (self::$manager === null) {
      $manager_class = self::$manager_class;
      if ($manager_class === null) $manager_class = static::MANAGER_CLASS;
      self::$manager = new $manager_class();
    }
    return self::$manager;
  }

  static final function __callStatic($name, $args) {
    $name = str::us2camel($name);
    return call_user_func_array([self::manager(), $name], $args);
  }

  #############################################################################

  static final function have_content(): bool { return self::manager()->haveContent(); }
  static final function add(?array $vs): void { self::manager()->add($vs); }
  static final function flush_content(bool $have_content=false): void {
    co::_write(self::manager()->flushContent($have_content));
  }
  static final function flush(bool $have_content=false): void {
    co::_write(self::manager()->flush($have_content));
  }
  static final function push($mark, ?array $start=null, ?array $end=null): void {
    co::_write(self::manager()->push($mark, $start, $end));
  }
  static final function pop($mark): void {
    co::_write(self::manager()->pop($mark));
  }

  static final function srow($options=null): void {
    co::_write(self::manager()->startRow($options));
  }
  static final function row($options=null): void {
    co::_write(self::manager()->row($options));
  }
  static final function col($size, $options=null): void {
    co::_write(self::manager()->col($size, $options));
  }
  static final function panel($title, $options=null): void {
    co::_write(self::manager()->panel($title, $options));
  }
  static final function epanel(): void {
    co::_write(self::manager()->endPanel());
  }
  static final function ecol(): void {
    co::_write(self::manager()->endCol());
  }
  static final function erow(): void {
    co::_write(self::manager()->endRow());
  }
  static final function end(): void {
    co::_write(self::manager()->end());
  }

  #############################################################################

  static final function _write(?iterable $vs): void {
    if ($vs === null) return;
    self::manager()->add($vs);
  }
  static final function _print(?iterable $vs): void {
    if ($vs === null) return;
    $ly = self::manager();
    $add_nl = false;
    foreach (c::flatten($vs) as $v) {
      $ly->add($v);
      $add_nl = true;
    }
    if ($add_nl) $ly->add(["\n"]);
  }

  static final function writep($vs): void { self::_write(q($vs)); }
  static final function printp($vs): void { self::_print(q($vs)); }

  static final function write($vs): void {
    self::flush_content(true);
    vo::write($vs);
  }
  static final function print($vs): void {
    self::flush_content(true);
    vo::print($vs);
  }

  #############################################################################
  # tous les éléments ci-dessous sont écrits en pending

  ## flush préalable
  static final function h1($vs): void { self::flush(); self::_print(v::h1($vs)); }
  static final function h2($vs): void { self::flush(); self::_print(v::h2($vs)); }
  static final function h3($vs): void { self::flush(); self::_print(v::h3($vs)); }
  static final function h4($vs): void { self::flush(); self::_print(v::h4($vs)); }
  static final function h5($vs): void { self::flush(); self::_print(v::h5($vs)); }
  static final function h6($vs): void { self::flush(); self::_print(v::h6($vs)); }

  static final function hr($vs=null): void { self::flush(); self::_print(v::hr($vs)); }

  ## pas de flush préalable
  static final function t($vs): void { self::_write(q($vs)); }

  static final function div($vs): void { self::_print(v::div($vs)); }
  static final function sdiv($vs=null): void { self::_write(v::sdiv($vs)); }
  static final function ediv(): void { self::_write(v::ediv()); }
  static final function mdiv(string $key, ?array $data=null, $vs=null): void { self::_print(v::mdiv($key, $data, $vs)); }

  static final function pre($vs): void { self::_print(v::pre($vs)); }
  static final function spre($vs=null): void { self::_print(v::spre($vs)); }
  static final function epre(): void { self::_print(v::epre()); }

  static final function p($vs): void { self::_print(v::p($vs)); }
  static final function sp($vs=null): void { self::_print(v::sp($vs)); }
  static final function ep(): void { self::_print(v::ep()); }

  static final function br($vs): void { self::_print(v::br($vs)); }

  static final function span($vs): void { self::_write(v::span($vs)); }
  static final function mspan(string $key, ?array $data=null, $vs=null): void { self::_print(v::mspan($key, $data, $vs)); }
  static final function a($vs, ?string $url=null): void { self::_write(v::a($vs, $url)); }
  static final function b($vs): void { self::_write(v::b($vs)); }
  static final function i($vs): void { self::_write(v::i($vs)); }
  static final function em($vs): void { self::_write(v::em($vs)); }
  static final function strong($vs): void { self::_write(v::strong($vs)); }

  static final function ul($vs): void { self::_print(v::ul($vs)); }
  static final function sul($vs=null): void { self::_print(v::sul($vs)); }
  static final function eul(): void { self::_print(v::eul()); }
  static final function ol($vs): void { self::_print(v::ol($vs)); }
  static final function sol($vs=null): void { self::_print(v::sol($vs)); }
  static final function eol(): void { self::_print(v::eol()); }
  static final function li($vs): void { self::_print(v::li($vs)); }

  static final function stable($vs=null): void { self::_print(v::stable($vs)); }
  static final function etable(): void { self::_print(v::etable()); }
  static final function sthead($vs=null): void { self::_print(v::sthead($vs)); }
  static final function ethead(): void { self::_print(v::ethead()); }
  static final function stbody($vs=null): void { self::_print(v::stbody($vs)); }
  static final function etbody(): void { self::_print(v::etbody()); }
  static final function tr($vs): void { self::_print(v::tr($vs)); }
  static final function str($vs=null): void { self::_print(v::str($vs)); }
  static final function etr(): void { self::_print(v::etr()); }
  static final function th($vs): void { self::_write(v::th($vs)); }
  static final function td($vs): void { self::_write(v::td($vs)); }

  static final function foreach(?iterable $values, ?callable $function): void { self::_write(v::foreach($values, $function)); }
}
