<?php
namespace nur\v\bs3\plugins;

use nur\A;
use nur\func;
use nur\v\BasePlugin;
use nur\v\js;
use nur\v\v;
use nur\v\vo;

class navtabPlugin extends BasePlugin {
  const COD_KEY = null;
  const TITLE_KEY = null;

  const FRAGMENT_PREFIX = "#nt:";

  /** @var array liste de tableaux [cod, title] */
  private $tabs;

  /** @var array liste des codes valides */
  private $tabCods;

  function __construct(?array $tabs=null) {
    $this->setTabs($tabs);
  }

  protected function filterTab($tab, ?array $tabs=null): bool {
    return false;
  }

  protected function getCod($tab): string {
    $codKey = static::COD_KEY;
    $tab = A::with($tab);
    if ($codKey !== null) return A::get($tab, $codKey, "");
    return A::first($tab, "");
  }

  protected function getTitle($tab): ?string {
    $titleKey = static::TITLE_KEY;
    $tab = A::with($tab);
    if ($titleKey !== null) return A::get($tab, $titleKey);
    else return A::second($tab);
  }

  private function getCodTitle($tab): array {
    $cod = $this->getCod($tab);
    $title = $this->getTitle($tab);
    if ($title == null) $title = $cod;
    return [$cod, $title];
  }

  function setTabs(?array $tabs=null): void {
    $tabs = A::with($tabs);
    $filteredTabs = [];
    $tabCods = [];
    foreach ($tabs as $tab) {
      if ($this->filterTab($tab, $tabs)) continue;
      $filteredTabs[] = $tab;
      $tabCods[] = $this->getCod($tab);
    }
    $this->tabs = $filteredTabs;
    $this->tabCods = $tabCods;
  }

  const HAVE_JQUERY = true;

  protected function jqSetup(): void {}
  protected function jqBeforeDeactivate(): void {}
  protected function jqAfterActivate(): void {}

  function printJquery(): void {
    $tabCods = $this->tabCods;
    if (!$tabCods) return;
    ?>
<script type="text/javascript">
  <?php $this->jqSetup(); ?>
  var NAV_TABS = <?=js::qvs($tabCods)?>;
  function activateTab(activeTab) {
    <?php $this->jqBeforeDeactivate(); ?>
    for (let i in NAV_TABS) {
      let tab = NAV_TABS[i];
      if (tab === activeTab) continue;
      $("#" + tab + "_tab").removeClass("active");
      $("#" + tab + "_panel").addClass("hide");
    }
    $("#" + activeTab + "_panel").removeClass("hide");
    $("#" + activeTab + "_tab").addClass("active");
    <?php $this->jqAfterActivate(); ?>
  }
  <?php foreach ($tabCods as $tabCod): ?>
  $(<?=js::qv("#${tabCod}_tab")?>).click(function() {
    activateTab(<?=js::qv($tabCod)?>);
    return false;
  });
  <?php endforeach; ?>
  function updateTab(initial=false) {
    let prefix = <?=js::qv(static::FRAGMENT_PREFIX)?>;
    let hash = window.location.hash;
    let hashOk = false;
    if (hash.startsWith(prefix)) {
      let tab = hash.slice(prefix.length);
      if ($("#" + tab + "_tab").length) {
        activateTab(tab);
        hashOk = true;
      }
    }
    if (!hashOk && initial) {
      for (let i in NAV_TABS) {
        let tab = NAV_TABS[i];
        if ($("#" + tab + "_tab").length) {
          activateTab(tab);
          break;
        }
      }
    }
  }
  $(window).on("hashchange", function() {
    updateTab();
  });
  updateTab(true);
</script>
<?php
  }

  const URL_KEY = null;
  protected function getUrl($tab): ?string {
    $urlKey = static::URL_KEY;
    if ($urlKey !== null) return A::get($tab, $urlKey);
    else return null;
  }

  const BADGE_KEY = null;
  protected function getBadge($tab): ?string {
    $badgeKey = static::BADGE_KEY;
    if ($badgeKey !== null) return A::get($tab, $badgeKey);
    else return null;
  }

  function paTabs(?string $curCod=null): void {
    $tabs = $this->tabs;
    if (!$tabs) return;
    vo::sul(["class" => "nav nav-tabs"]);
    foreach ($tabs as $tab) {
      [$cod, $title] = $this->getCodTitle($tab);
      vo::li([
        "id" => "${cod}_tab",
        "class" => $cod === $curCod? "active": null,
        "role" => "presentation",
        v::a([
          "href" => $this->getUrl($tab),
          q($title),
          v::span(["class" => "badge", $this->getBadge($tab)])
        ]),
      ]);
    }
    vo::eul();
  }

  function paStartPanel($cod): void {
    if (!is_string($cod)) $cod = $this->getCod($cod);
    vo::sdiv(["id" => "${cod}_panel"]);
  }

  function paEndPanel(): void {
    vo::ediv();
  }

  function printActions(?string $curCod, callable $printPanel, ?callable $beforePanels=null, ?callable $afterPanels=null): bool {
    $tabs = $this->tabs;
    if (!$tabs) return false;
    $func = func::_prepare($printPanel);
    $this->paTabs($curCod);
    if ($beforePanels !== null) $beforePanels();
    foreach ($this->tabs as $tab) {
      $this->paStartPanel($tab);
      func::_call($func, [$tab, $this]);
      $this->paEndPanel();
    }
    if ($afterPanels !== null) $afterPanels();
    return true;
  }
}
