<?php
 
namespace elanpl\L3;
 
class Application{
    public $config; // L3 Config object
    public $request; // build from received HTTP request or created in L3 Config object
    public $response; // response to be send
    public $router; // routing engine
    public $serialization; // serialization engine
    public $baseDirecotry; // directory root of the application
    public $controllersDirecotry; // subdirectory/namespace part added to controller class 
    public $viewsDirecotry; // subdirectory to search for the view files
    public $applicationDirectory; // subdirectory/namespace part of the application
    public $controller; //Active controller
    public $module; //Active module
    public $action; //Active action
 
    public function __construct($config){
        //set L3 application config
        $this->config = $config;
        // directory root of the application
        $this->baseDirecotry = $config->getBaseDirectory();
        // subdirectory/namespace part added to controller class
        $this->controllersDirecotry = $config->getControllersDirectory();
        // subdirectory to search for the view files 
        $this->viewsDirecotry = $config->getViewsDirectory();
        // subdirectory/namespace part of the application
        $this->applicationDirectory = $config->getApplicationDirectory();
        //create request object
        $this->request = $this->config->getRequest();
        //create router object
        $this->router = new Router($this->config->getRouting());
        //create response objcet
        $this->response = new Response();
 
        //create serialization object
        $this->serialization = new Serialization(); 
    }
 
    public function basePath(){
        return strstr($_SERVER['REQUEST_URI'], $this->request->path, true);
    }
 
    public function relPath($file){
        return ($this->router->depth>0 ? str_repeat("../", substr($this->request->path,-1)=='/'?$this->router->depth:$this->router->depth-1) : "" ).$file; 
    }
 
    public function link($name, $parameters){
        return $this->router->link($name, $parameters);
    }
 
    /*
    //not need - PSR-4 autoload handles that
    function IncludeControler($Controller){
        include_once(_L3_CONTROLLER_PATH.$Controller.'.php');
    }*/
 
    public function findControllerInCallStack($search_level=5){
        //search for controller, action and module if present
        $controller = "";
        $module = "";
        $action = "";
        $match = array();
 
        //analize the call stack
          $call_stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, $search_level);
        
        for($i=0; $i<$search_level; $i++){
            if(preg_match(
                    $pattern = '#('.$this->applicationDirectory.')(\\\\(?P<module>.+))?\\\\'.$this->controllersDirecotry.'\\\\(?P<controller>.+)#',
                    $call_stack[$i]['class'],
                    $match
                )
            ){
                $action = $call_stack[$i]['function'];
                $module = $match['module'];
                $controller = $match['controller'];
                break;
            }
        }
 
        return array(
            'module' => $module,
            'controller' => $controller,
            'action' => $action
        );
    }
 
    function runControllerAction($controllerAction, $parameters){
        
        //prepare object and action name
        /*
        TODO ...
        if(is_object($this->controler) && (is_a($this->controler,'L2_controler') || is_subclass_of($this->controler,'L2_controler'))){
            if(is_string($this->action)){
                $controler_object = $this->controler;
                $controler_action = $this->action;
            }
        }
        else if(is_string($this->controler)){
            if(is_string($this->action)){
                $this->includeControler($this->controler);