<?php

namespace elanpl\L3;

class View{
    protected $viewFileExtension;
    protected $viewFile;
    protected $context;
    public $_L3; //The L3 instance

    public function __construct(){
        $numargs = func_num_args();
     
        if ($numargs == 0) {
            $view = "";
            $context = array();
        }
        else if ($numargs == 1) {
            $arg = func_get_arg(0);
            if(is_object($arg) && $arg instanceof ViewModel){
                if(method_exists($arg, 'getContext')){
                    $context = $arg->getContext();
                }
                else{
                    $context = array();
                    $context['vm'] = $arg;
                }

                if(method_exists($arg, 'getView')){
                    $view = $arg->getView();
                }
                else{
                    $view = $arg;
                }

                if(isset($arg->_L3)){
                    $this->_L3 = $arg->_L3;
                }
            }
            else{
                $view = "";
                $context = $arg;
            }
        }
        else {
            $arg = func_get_arg(0);
            if($arg instanceof Application){
                $this->_L3 = $arg;
                $view = func_get_arg(1);
                $context = func_get_arg(2);
            }
            else{
                $view = func_get_arg(0);
                $context = func_get_arg(1);
            }
        }

        if(!isset($this->_L3)){
            // if an Application object was not injected, take it form the global context...
            global $_L3;
            $this->_L3 = $_L3;
        }
        

        if($this->viewFile = $this->find($view)){
            if(!isset($this->viewFileExtension)){
                foreach($this->_L3->viewEngines->getRegisteredFileExtensions() as $extension){
                    if(substr($this->viewFile, -strlen($extension)) == $extension){
                        $this->viewFileExtension = $extension;
                        break;
                        //$this->viewFileExtension = ".".pathinfo($this->viewFile, PATHINFO_EXTENSION);
                    }
                }
            }
        }
        else{
            if(is_object($view)){
                $string_view = 'matched for class: '.get_class($view);
            }
            else{
                $string_view = $view;
            }
            throw new \Exception("View file:\"$string_view\" not found!");
        }
        $this->context = $context;
    }

    public function render(){
        if ($viewEngine = $this->_L3->viewEngines->get($this->viewFileExtension)){

            $viewEngineClass = $viewEngine->class;
            if(isset($viewEngine->config)){
                $view = new $viewEngineClass($this->_L3, $viewEngine->config);
            }
            else{
                $refl = new \ReflectionClass($viewEngineClass);
                if($refl->inNamespace()&&class_exists($refl->getNamespaceName().'\\Config')){
                    $view = new $viewEngineClass($this->_L3, $refl->getNamespaceName().'\\Config');
                }
                else{
                    $view = new $viewEngineClass($this->_L3);
                }
            }    
            return $view->render($this->viewFile, $this->context);
        }
        else{
            throw new \Exception("View Engine not found for the view file extension:\"".$this->viewFileExtension."\"!");
        }
    }

    public function find($view){
        //find the view file
        if(is_string($view) && is_file($view)){
            // full path was provided...
            return $view;
        }
        else{
            // search for the view file
            
            //search for controller, action and module if present  
            if(is_object($view) && $view instanceof ViewModel){
                $controller = $view->getController();
                $module = $view->getModule();
                $action = $view->getAction();
                $view = "";
            }
            else{                    
                
                $match = $this->_L3->findControllerInCallStack();

                $controller = $match['controller'];
                $module = $match['module'];
                $action = $match['action'];     
            }
            //locate the view file
            
            // The search order:
            // check [module/]views/controller/action/ directory (file)
            // check [module/]views/controller/ directory (file)
            // check [module/]views/

            $viewsPath = $this->_L3->baseDirectory.$this->_L3->applicationDirectory.DIRECTORY_SEPARATOR
                .($module!=""?$module.DIRECTORY_SEPARATOR:"").$this->_L3->viewsDirectory.DIRECTORY_SEPARATOR;

            $dirs = array();

            $dirs[] = $viewsPath.$controller.DIRECTORY_SEPARATOR.$action;
            $dirs[] = $viewsPath.$controller.DIRECTORY_SEPARATOR;
            $dirs[] = $viewsPath;

            foreach($dirs as $dir){
                // check if the file exists
                if(is_file($found = str_replace('\\', DIRECTORY_SEPARATOR, $dir.($action!=""&&$view!=""?DIRECTORY_SEPARATOR:"").$view))){
                    return $found;
                }
                // try to add extension and check again
                else foreach($this->_L3->viewEngines->getRegisteredFileExtensions() as $registeredExtension){
                    if(is_file($found = str_replace('\\', DIRECTORY_SEPARATOR, $dir.($action!=""&&$view!=""?DIRECTORY_SEPARATOR:"").$view.$registeredExtension))){
                        $this->viewFileExtension = $registeredExtension;
                        return $found;
                    }
                }
            }
            

        }
        return null;
    }
}