<?php

if (!defined('XOOPS_ROOT_PATH')) exit();

require_once XOOPS_ROOT_PATH."/class/XCube_ActionFilter.class.php";
require_once XOOPS_ROOT_PATH."/class/XCube_ModuleController.class.php";
require_once XOOPS_ROOT_PATH."/class/XCube_BlockProcedure.class.php";
require_once XOOPS_ROOT_PATH."/class/XCube_RenderSystem.class.php";
require_once XOOPS_ROOT_PATH."/class/XCube_EventArgs.class.php";

/**
 * Virtual front controller class
 */
class XCube_Controller
{
	var $mRoot;

	var $mBlockChain = array();
	var $mFilterChain = array();
	
	/**
	 * XoopsLogger Instance
	 * @access protected
	 */
	var $mLogger;
	
	/**
	 * XoopsErrorHandler instance
	 * @access protected
	 */
	var $mErrorHandler;


	/**
	 * Database instance
	 * @access protected
	 */
	var $mDB;
	
	/**
	 * Array
	 * @access protected
	 */
	var $mConfig;
	
	var $mDebugger;
	
	var $mUser;


	/**
	 * @access public
	 */
	var $mLanguage;

	var $mModuleController;

	var $mRenderSystem;
	
	/**
	 * Instance to implement the action process of this controller
	 * @access private
	 */
	var $mActionStrategy=null;

	function XCube_Controller()
	{
		$this->mBlockChain=array();
		$this->mFilterChain=array();
	}
	
	function prepare(&$root)
	{
		$this->mRoot=&$root;
	}

	/**
	 * @access public
	 */
	function executeCommon()
	{
		//
		// Setup Filter chain and execute the process of these filters.
		//
		$this->_setupFilterChain();
		$this->_processFilter();

		$this->mRoot->setEventManager($this->_createEventManager());
		$this->mRoot->setServiceManager($this->_createServiceManager());
		
		// ^^;
		$this->_setupErrorHandler();

		$this->_setupEnvironment();
		
		$this->_setupLogger();

		$this->_setupDB();

		$this->_setupConfig();
		
		$this->_setupDebugger();

		$this->_processPreBlockFilter();	// What's !?

		$languageManager =& $this->_createLanguageManager();
		$this->mRoot->setLanguageManager($languageManager);

		$this->_processHostAbstractLayer();

		$this->_setupSession();

		$this->_setupUser();

		$this->_setupModuleController();

		$this->_setupRenderSystem();

		$this->_processModuleController();
	}
	
	/**
	 * Create filter chain.
	 * @access protected
	 */
	function _setupFilterChain()
	{
	}

	function addActionFilter(&$filter)
	{
		$this->mFilterChain[]=&$filter;
	}

	/**
	 * Create the instance of XoopsErrorHandler class, and set it to member property.
	 * @access protected
	 */
	function _setupErrorHandler()
	{
	}

	function _setupEnvironment()
	{
	}
	
	/**
	 * Create the instance of XoopsLogger class, and set it to member property.
	 * @access private
	 */
	function _setupLogger()
	{
	}
	
	/**
	 * Create the instance of DataBase class, and set it to member property.
	 * @access protected
	 */
	function _setupDB()
	{
	}
	
	/**
	 * @access public
	 */
	function &getDB()
	{
		return $this->mDB;
	}

	function _setupConfig()
	{
	}

	/**
	 * Set debbuger object to member property.
	 * @return void
	 */
	function _setupDebugger()
	{
	}

	function &_createLanguageManager()
	{
		require_once XOOPS_ROOT_PATH."/class/XCube_LanguageManager.class.php";
		$languageManager=new XCube_LanguageManager($this->mConfig['language']);
		return $languageManager;
	}

	/**
	 * We need this method really??
	 */
	function _processHostAbstractLayer()
	{
	}

	/**
	 * Setup handler for session, then start session.
	 * @return void
	 */
	function _setupSession()
	{
	}
	
	function _setupUser()
	{
		$eventManager=&$this->mRoot->getEventManager();
		if($eventManager!=null) {
			$eventArgs= new LoginEventArgs();
			$eventManager->raiseEvent("Site.Login",$this,$eventArgs);

			if($eventArgs->hasUser())
				$this->mUser=&$eventArgs->getUser();
		}
	}
	
	function _setupModuleController()
	{
		$this->mModuleController=new XCube_ModuleController($this);
	}
	
	/**
	 * Return module controller.
	 * @return XCube_ModuleController
	 */
	function &getModuleController()
	{
		return $this->mModuleController;
	}
	
	/**
	 * @return bool We have to return boolean in this method really??
	 * @todo move this method to Base_Controller
	 */
	function _processModuleController()
	{
		$this->mModuleController->prepare();

		if($this->mModuleController->isModuleProcess()) {
			if(!$this->mModuleController->isActive())
				die('NOT ACTIVE');	///< @todo

   			if(!$this->mModuleController->hasPermission())
				XCube_Utils::redirectHeader(XOOPS_URL,1,_NOPERM);	// TODO Depens on const message catalog.

			$this->mModuleController->setupLanguage();
			
			return true;
		}
		
		return false;
	}

	/**
	 * Return logger instance.
	 * @return Object
	 */
	function &getLogger()
	{
		return $this->mLogger;
	}
	

	/**
	 * Return logger instance.
	 * @return XoopsErrorHandler
	 */
	function &getErrorHandler()
	{
		return $this->mErrorHandler;
	}


	/**
	 * This method create RenderSystem and set it to own property.
	 */
	function executeHeader()
	{
		//
		// TODO Now, I done for working admin panel.
		//
		$renderSystem =& $this->mRoot->getRenderSystem($this->mModuleController->getDependRenderSystem());

		// TODO
		$this->mRenderSystem =& $renderSystem;
		
		$this->mRenderSystem->prepare($this);
		
		$this->_setupBlock();
		$this->_processBlock();
	}

	/**
	 * This method only show you the concept process of this system.
	 * @return void
	 */
	function execute()
	{
		// $this->executeCommon();
		// $this->executeHeader();
	}
	
	function getConfig($id=null)
	{
		if($id) {
			return $this->mConfig[$id];
		}
		else {
			return $this->mConfig;
		}
	}
	
	
	function _processFilter()
	{
		for ($i = 0; $i < count($this->mFilterChain); $i++) {
			$this->mFilterChain[$i]->preFilter($this);
		}
	}
	
	function _setupBlock()
	{
	}

	function _processBlock()
	{
		$i=0;
		foreach($this->mBlockChain as $blockProcedure) {
			$blockProcedure->execute($this,$this->getUser());
			if($blockProcedure->hasResult()) {
				$this->mRenderSystem->renderBlock($blockProcedure);
			}
			unset($blockProcedure);
		}
	}

	function _processPreBlockFilter()
	{
		for ($i = 0; $i < count($this->mFilterChain); $i++) {
			$this->mFilterChain[$i]->preBlockFilter($this);
		}
	}
	
	function &_createEventManager()
	{
		require_once XOOPS_ROOT_PATH."/class/XCube_EventManager.class.php";
		$eventManager=new XCube_EventManager();
		return $eventManager;
	}

	function &_createServiceManager()
	{
		require_once XOOPS_ROOT_PATH."/class/XCube_ServiceManager.class.php";
		$serviceManager=new XCube_ServiceManager();
		return $serviceManager;
	}

	function &getDebugger()
	{
		return $this->mDebugger;
	}
	
	/**
	 * Create and setup RenderSystem.
	 * @deprecated
	 */
	function _setupRenderSystem()
	{
		// TODO remove this method.
	}
	
	/**
	 * Retern RenderSystem
	 * @return XCube_RenderSystem
	 */
	function &getRenderSystem()
	{
		return $this->mRenderSystem;
	}
	
	function executeView()
	{
		$this->mRenderSystem->display();
	}
	
	function setActionStrategy(&$actionStrategy)
	{
		$this->mActionStrategy=&$actionStrategy;
		$this->mActionStrategy->prepare($this);
	}

	/**
	 * @access protected
	 */
	function _processAction()
	{
		if($this->mActionStrategy!==null)	// is_object
			$this->mActionStrategy->execute($this);
	}
	
	function executeAction()
	{
		$this->_processAction();
	}
	
	/**
	 * TODO We may change this name to forward()
	 */
	function executeForward($url, $time = 0, $message = null)
	{
		// check header output
		header("location: ".$url);
		exit();
	}

	function executeRedirect($url, $time = 1, $message = null)
	{
		// TODO
	}
}

?>