<?php
/**
 * @copyright (c) Kufer Software GmbH, Oderstraße 7, D-84453 Mühldorf
 */

namespace Kufer\Web\KuferTools\Basis\UseCaseBuilder;

class PrimaryActionBus implements ActionBus
{
  
  private $listenersByAction = array();

  
  private $actionTree = array();

  
  private $running = true;

  public function shutdown(): void
  {
    $this->running = false;
  }

  public function addListener(string $actionName, ActionListener $listener)
  {
    if (!isset($this->listenersByAction[$actionName])) {
      $this->listenersByAction[$actionName] = array();
    }

    $this->listenersByAction[$actionName][] = $listener;
  }

  public function trigger(Action $action): void
  {
    $actionSequence = array($action->getName());
    $this->addToActionTree($actionSequence);

    $this->triggerByActionName(new ChildActionBus($this, $actionSequence), $action);
  }

  public function triggerInActionSequence(array $actionSequence, Action $action): void
  {
    $actionSequence = array_merge($actionSequence, array($action->getName()));

    $this->triggerByActionName(new ChildActionBus($this, $actionSequence), $action);
  }

  private function triggerByActionName(ChildActionBus $actionBus, Action $action): void
  {
    if (!$this->running) {
      return;
    }

    $this->addToActionTree($actionBus->getActionSequence());

    foreach (($this->listenersByAction[$action->getName()] ?? array()) as $listener) {
      $listener->action($actionBus, $action);
      if (!$this->running) {
        return;
      }
    }
  }

  
  private function addToActionTree(array $actionSequence): void
  {
    $actionTree = &$this->actionTree;
    foreach ($actionSequence as $actionName) {
      if (!isset($actionTree[$actionName])) {
        $actionTree[$actionName] = array();
      }

      $actionTree = &$actionTree[$actionName];
    }
  }
}