<?php

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

require_once XOOPS_ROOT_PATH . "/class/XCube_Event.class.php";

/**
 * This class manages plural events.
 * This class supports substitute registration for speedup.
 */
class XCube_EventManager
{
	var $_mEvents=array();

	var $_mReserveEventList=array();
	var $_mRegistedFlags=array();
	var $_mProxyRegisters=array();
	
	function XCube_EventManager()
	{
	}
	
	function prepare()
	{
	}
	
	function add($eventName,&$delegate)
	{
		if(!isset($this->_mEvents[$eventName]))
			$this->_mEvents[$eventName] = new XCube_Event($eventName);

		$this->_mEvents[$eventName]->add($delegate);
	}
	
	function setAnchorDelegate($eventName,&$delegate)
	{
		if(!isset($this->_mEvents[$eventName]))
			$this->_mEvents[$eventName] = new XCube_Event($eventName);

		$this->_mEvents[$eventName]->setAnchorDelegate($delegate);
	}
	
	function replaceEvent($eventName,&$eventHandler)
	{
		if(isset($this->_mReserveEventList[$eventName])) {
			unset($this->_mReserveEventList[$eventName]);
		}
		if(isset($this->_mRegistedFlags[$eventName])) {
			unset($this->_mRegistedFlags[$eventName]);
		}
		if(isset($this->_mEvents[$eventName])) {
			if(strtolower(get_class($this->_mEvents[$eventName]))=="xcube_event") {
				//
				// TODO : omg! We access private property.
				//
				foreach($this->_mEvents[$eventName]->_mDelegates as $delegate) {
					$eventHandler->_mDelegates[]=$delegate;
					unset($delegate);
				}
				unset($this->_mEvents[$eventName]);
				$this->_mEvents[$eventName]=&$eventHandler;
			}
		}
		else {
			$this->_mEvents[$eventName]=&$eventHandler;
		}
	}

	function raiseEvent($eventName,&$sender,&$eventArgs)
	{
		if(isset($this->_mReserveEventList[$eventName])&&$this->_mRegistedFlags[$eventName]==false) {
			$this->_processProxyRegist($eventName);
		}
		
		if(isset($this->_mEvents[$eventName])) {
			$this->_mEvents[$eventName]->raiseEvent($sender,$eventArgs);

			return true;
		}
		return false;
	}

	function addProxyRegister(&$register)
	{
		$i=count($this->_mProxyRegisters)+1;
		$this->_mProxyRegisters[$i]=&$register;
		
		$list=$register->getEventNameList();
		foreach($list as $name) {
			if(!isset($this->_mReserveEventList[$name])) {
				$this->_mReserveEventList[$name]=array();
				$this->_mRegistedFlags[$name]=false;
			}

			$this->_mReserveEventList[$name][]=$i;
		}
	}
	
	function _processProxyRegist($eventName)
	{
		$this->_mRegistedFlags[$eventName]=true;
		foreach($this->_mReserveEventList[$eventName] as $i) {
			$this->add($eventName,$this->_mProxyRegisters[$i]->createDelegate($eventName));
		}
	}
}

/**
 * This class tells a manager about a list of the event that the Delegate which this class can create.
 * And this class creates Delegate when the manager needs Delegate.
 * Developer does not need to use this by all means.
 */
class XCube_EventProxyRegister
{
	/**
	 * @return array
	 */
	function getEventNameList()
	{
	}
	
	function &createDelegate($name)
	{
		$ret =null;
		$methodName=str_replace(".","_","create".ucfirst($name)."Delegate");
		if(method_exists($this,$methodName)) {
			$ret=&call_user_func(array($this,$methodName));
		}

		return $ret;
	}
}

/**
  *
  * Static Utility methods for XCube_EventManager
  *
  */
class XCube_EventUtils
{
    /**
    Simple Raise Event method;
    */
    function &quickRaiseEvent($event, $eventArgs = array())
    {
        $root=&XCube_Root::getSingleton();
        if ($root->mEventManager->raiseEvent($event, $root->mController, $eventArgs)) {
            return $eventArgs;
        } else {
			$ret = false;
            return $ret;
        }
    }

    /**
    Simple Text Filterling with Event mechanism
    */
    function quickApplyFilter($filter, $string, $optionArgs = array())
    {
        $root=&XCube_Root::getSingleton();
        $eventArgs = array_merge(array('string' => $string), $optionArgs);
        if ($root->mEventManager->raiseEvent($filter, $root->mController, $eventArgs)) {
            return $eventArgs['string'];
        } else {
            return $string;
        }
    }
}
?>