<?php
/**
 * @copyright NetMonsters <team@netmonsters.ru>
 * @link http://netmonsters.ru
 * @package Majestic
 * @subpackage app
 * @since 2010-02-24
 * @version SVN: $Id$
 * @filesource $URL$
 */

class FrontController
{
    /**
     * @var Router
     */
    protected $router;

    /**
     * @var string
     */
    protected $view = 'PHPView';

    protected $base_url = '';

    /**
     * @var FrontController
     */
    protected static $instance;


    private function __construct()
    {
        ErrorHandler::init();
        if (DEBUG == true) {
            Profiler::getInstance()->start();
        }
        $this->router = new Router();
    }

    /**
     * Refuse cloning
     */
    private function __clone(){}
    
    /**
     * @return FrontController
     */
    static public function getInstance()
    {
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * @param string $view
     * @return FrontController
     */
    public function setView($view)
    {
        $this->view = $view;
        return $this;
    }

    /**
     *
     * @return iView
     */
    public function getView($view = null)
    {
        $view = ($view) ? $view : $this->view;
        return new $view(Config::get($view));
    }

    /**
     * @param string $url
     */
    public function setBaseUrl($url)
    {
        $this->base_url = rtrim($url, '/');
        return $this;
    }

    public function getBaseUrl()
    {
        return $this->base_url;
    }

    /**
     * @return Router
     */
    public function getRouter()
    {
        return $this->router;
    }

    public function execute()
    {
        try {
            $request = Env::getRequestUri(true);
            $route = $this->getRouter()->route($request);
            if (!$route) {
                throw new Error404Exception('Route for "' . $request . '" not found');
            }

            $action_class = $route->getAction();
            if (!class_exists($action_class)) {
                throw new GeneralException('Action class "' . $action_class . '" not found.');
            }

            $action = new $action_class();
            $layout_class = $route->getLayout();
            if (!class_exists($layout_class)) {
                throw new GeneralException('Layout class "' . $layout_class . '" not found.');
            }

            $layout = new $layout_class();
            $html = $layout->fetch($action);
            if (DEBUG) {
                if (is_subclass_of($action, 'AjaxAction')) {
                    Profiler::getInstance()->getJson();
                } else {
                    $html = Profiler::getInstance()->end($html);
                }
            }
            return $html;
        } catch(Exception $e) {
            if (DEBUG == true) {
                if (!headers_sent()) {
                    header('HTTP/1.0 500 Internal Server Error');
                }
                return ErrorHandler::showDebug($e);
            }
            $layout = new ErrorLayout();
            return $layout->fetch(new ErrorAction($e));
        }
    }
}