<?php

namespace Hwapx\Core\Library;

use F3;
use Prefab;

class ModuleManager extends Prefab {
  protected $f3         = null;
  protected $module_dir = '';
  public    $modules    = array();
  public    $roles      = array();

  public function __construct($f3) {
    $this->f3         = $f3;

    $this->module_dir = $f3->get('app.module.dir');
  }

  public function load() {
    $locale_path = $this->f3->get('LOCALES');

    $this->f3->concat('AUTOLOAD', "|".$this->module_dir);
    $this->f3->concat('UI', "|".$this->module_dir);

    foreach(glob($this->module_dir."*/*/", GLOB_ONLYDIR) as $mdir) {
      $route_file = $mdir."routes.ini";
      if(file_exists($route_file))
        $this->f3->config($route_file);

      $config_file = $mdir."config.ini";
      if(file_exists($config_file))
        $this->f3->config($config_file);

      $autoload_file = $mdir."vendor/autoload.php";
      if(file_exists($autoload_file))
        require $autoload_file;

      $locale_path .= "|".$mdir.'dict/';

      $vendor = ucfirst(basename(dirname($mdir)));
      $module = ucfirst(basename($mdir));
      $path   = "$vendor\\$module";
      $class  = "\\$path\\Module";

      $instance = new $class($this->f3);

      if(defined($class.'::roles'))
          $this->roles[str_replace('\\', '.', strtolower($path))] = constant($class.'::roles');
      else if(isset($class::$roles))
          $this->roles[str_replace('\\', '.', strtolower($path))] = $class::$roles;

      $this->modules[$path] = $instance;
    }

    $this->f3->set('LOCALES', $locale_path);

    foreach ($this->modules as $ns => $instance) {
      if(method_exists($instance, 'boot')) {
        $instance->boot($this->f3);
      }
    }
  }

  public function roles($module_ns = null) {
    $result = array();

    if($module_ns) {
      $module_ns = str_replace('\\', '.', strtolower($module_ns));

      foreach($this->roles[$module_ns] as $role => $label)
        $result[$role] = $this->hasRole($module_ns, $role);
    } else {
      foreach($this->roles as $module => $roles)
        foreach($roles as $role => $label)
          $result[$module][$role] = $this->hasRole($module, $role);
    }

    return $result;
  }

  public function roleList($module_ns = null) {
    $result = array();

    if($module_ns !== null) {
      foreach($this->roles[$module_ns] as $role => $label)
        $result[$module_ns.'.'.$role] = $label;
    } else {
      foreach($this->roles as $module => $roles)
        foreach($roles as $role => $label)
          $result[$module.'.'.$role] = $label;
    }

    return $result;
  }

  public function hasRole($module_ns, $role = null) {
    if($module_ns === null && $role === null) return true; 
    if($this->f3->exists('SESSION.admin', $user)) {
      $module_ns = str_replace('\\', '.', strtolower($module_ns));
      if(!$role)
        $role_ns = $module_ns;
      else
        $role_ns = $module_ns.'.'.$role;

      $roles = isset($user['group']['roles']) ? $user['group']['roles'] : array();

      return (isset($user['id']) && $user['id'] == 1) || in_array($role_ns, $roles);
    }
    return false;
  }

  public function checkRole($module_ns, $role = null) {
    if(!$this->hasRole($module_ns, $role)) {
      $logger = new \Log(date('Y-m-d').'_user.log');
      $logger->write('Usuário "'.$this->f3->get('SESSION.admin.email').'" teve o acesso bloqueado a função "'.$this->roles[$role].'" por falta de permissões');

      flash('error', 'Você não tem permissão para acessar o recurso solicitado.');
      $this->f3->reroute('@admin_dashboard');
    }
  }

  public function moduleNamespaceOf($class) {
    if(is_string($class)) {
      $ns = $class;
    } elseif(is_object($class)) {
      $reflection = new \ReflectionObject($class);
      $ns = $reflection->getNamespaceName();
    } else {
      $reflection = new \ReflectionClass($class);
      $ns = $reflection->getNamespaceName();
    }

    if(preg_match('/^[^\\\\]+\\\\[^\\\\]+/', $ns, $match))
      return $match[0];
    else
      return null;
  }

  public function moduleOf($class) {
    $ns = $this->moduleNamespaceOf($class);

    if($ns && isset($this->modules[$ns]))
      return $this->modules[$ns];
    else
      return null;
  }
}