<?php

namespace Tools;

/**
 * Allow user to manage hooks
**/
class Hooks
{
    /**
     * @var \Tools\Context $context
     * /core/tools/Context.php
     * Contains website's informations
    **/
    private $context;

    /**
     * @var array( string: hookName => module Id )
    **/
    private $hooks;

    /**
     * @var SplStack $currentHook
     * Contains current trigerred event
    **/
    private $currentHook;

    /**
     * @var \Tools\HookEvent $currentHook
     * get current hook event
     **/

    /**
     * ctor. Initialize context for having them passed to hook as parameter
    **/
    public function __construct(&$context)
    {
        $this->context = $context;
        $this->currentHook = array();
		$this->hooks = array();
    }

    /**
     * @param \Tool\AModule $module
     * @param string $hookname
     * Attach module $module to $hookName
     * Can only be called while installing the module.
     * When fired, the AModule::doAction($hookName, $context) function will be called.
    **/
    public function register($module, $hookName)
    {
        if (!\Tools\ModuleManager::isInstalling())
            throw new \Exception("You can only register hooks while installing");
		if (!isset($this->hooks[$hookName]))
			$this->hooks[$hookName] = array();
        $this->hooks[$hookName][] = $module->entity->id;
		$moduleHook = new \Entity\ModuleHook();
		$moduleHook->module_id = $module->entity->id;
		$moduleHook->hookName = $hookName;
		$moduleHook->hookPosition = 10;
		$moduleHook->save();
    }

    /**
     * @param string $hookName
     * @return number of modules successfully reached
     * fire the hook hookName
     * call the AModule::doAction($hookEvent) function for each attached modules
    **/
    public function trigger($hookName, $params =null)
    {
        if (empty($this->hooks[$hookName]))
            return 0;
        $hookEvent = new HookEvent($hookName, $this->context, $params);
        array_push($this->currentHook, $hookEvent);
        $result = 0;
        foreach ($this->hooks[$hookName] as $module_id)
        {
            $module = $this->context->moduleManager->getModuleFromId($module_id);
            if (!$module)
                continue;
            $module->doAction($hookEvent);
            $result++;
        }
        array_pop($this->currentHook);
        return $result;
    }

    /**
     * @param string $hookName
     * @return boolean
     * Check if $hookName is treating
    **/
    public function isInHook($hookName)
    {
        foreach ($this->currentHook as $i)
            if ($i->hookName == $hookName)
                return true;
        return false;
    }

    /**
     * @param array(\Entity\ModuleHook) $module_hookEntities entities to load
     * Reload hooks from entities
    **/
    public function loadHooks($hookEntities)
    {
        $this->hooks = array();
        foreach ($hookEntities as $i)
            $this->hooks[$i->hookName][] = (int) $i->module_id;
    }

	/**
	 * Getter
	**/
    public function __get($key)
    {
        switch ($key)
        {
            case "currentHook": return end($this->currentHook);
        }
        throw new \Exception("Cannot access attribute {$key}");
    }
}

