<?php 

namespace Tools;

/**
 * Container all modules.
 * Allow module managment
**/
class ModuleManager
{
    /**
     * @var \Tools\Context $context
     * /core/tools/Context.php
     * Contains website's informations
    **/
    private $context;

    /**
     * @var array(\Tool\AModule) $modules
     * /core/tools/AModule.php
     * Contains all loaded modules
     * Can be accessed read-only via $instance->modules
    **/
    private $modules = array();

    /**
     * @var _id_{ID}
     * Get the module identified with id ID
     * ex: $context->moduleManager->_id_2 will return module with id 2
    **/

    /**
     * @param \Tool\Context $context
     * Load all active modules from database.
     * Enable hooks for these modules
     * Disable them if the module cannot be loaded
    **/
    public function __construct(&$context)
    {
        $this->context = $context;
        $modulesRoot = $context->router->modulesPath;
        $modules = \Entity\Module::getActivated();
        $ids = array();
        foreach ($modules as $i)
        {
            $modulePath = "{$modulesRoot}{$i->directory}/main.php";
            if (file_exists($modulePath) && $this->loadModule($modulePath, $i))
            {
                $ids[] = $i->id;
            }
            else
            {
                die ("out");
                $i->active = false;
                $i->save();
            }
        }
        $context->hookManager->loadHooks(\Entity\ModuleHook::getModules($ids));
    }

    /**
     * @param string $path path to module's main file
     * @param \Entity\Module $module module's database object to load
     * /core/models/Module.php
     * @return TRUE on success
     * Will try to load module located at $path.
     * This function will include the main.php file located in the module's directory
     * The file MUST return an AModule object to be considered as successfull
     * /core/tools/AModule.php
    **/
    private function loadModule($path, $module)
    {
        $mod = include_once($path);
        if (!$mod || !($mod instanceof \Tools\AModule))
            return false;
        $mod->setContext($this->context);
        $mod->setEntity($module);
        $this->modules[] = $mod;
        return true;
    }

    /*
     * TODO revoir tout
     * @return array(AModule)
     * Will load every modules, and return them.
    **/
    public function listAvailableModules()
    {
        $modulesRoot = $context->router->modulesPath;
        $result = array();
        $modules = scandir($modulesRoot, SCANDIR_SORT_NONE);
        foreach ($modules as $i)
        {
            $path = $modulesRoot.$i;
            if ($i == '.' || $i == '..' || !is_dir($path))
                continue;
            $this->loadModule($path);
        }
    }

    /**
     * @param int $id
     * @return AModule on success, FALSE on failure (no such ID / module not loaded)
     * Get the module identified with id ID
    **/
    public function getModuleFromId($id)
    {
        foreach ($this->modules as $i)
        {
            if ($i->entity->id == $id)
                return $i;
        }
        return FALSE;
    }

	/**
	 * Getter
	**/
    public function __get($key)
    {
        switch ($key)
        {
            case "modules":
                return $this->modules; break;
        }
        if (substr($key, 0, 4) == "_id_")
            return $this->getModuleFromId((int) substr($key, 4));
        throw new \Exception("Cannot access attribute {$key}");
    }
}

