<?php
/**
 * @version   1.6 October 30, 2011
 * @author    RocketTheme http://www.rockettheme.com
 * @copyright Copyright (C) 2007 - 2011 RocketTheme, LLC
 * @license   http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 only
 *
 *
 *
 * Original Author and Licence
 * @author Mateusz 'MatheW' Wójcik, <mat.wojcik@gmail.com>
 * @link http://mwojcik.pl
 * @version 1.0
 * @license GPL
 */

/**
 * @throws RokCommon_Cache_Exception
 */
class RokCommon_Cache
{

	/**
	 * Array of driver strategies
	 *
	 * @var array
	 */
	protected $drivers = array();

	/**
	 * Name of default driver
	 *
	 * @var string
	 */
	protected $defaultDriver = 'NULL';

	/**
	 * Default cache lifetime in seconds
	 *
	 * @var int
	 */
	protected $defaultLifeTime = 300;

	/**
	 * Specifies if debug mode is on
	 *
	 * @var boolean
	 */
	protected $debugMode=false;

    public static function addDriverPath($path) {
        try {
            if (!RokCommon_ClassLoader::isLoaderRegistered('CacheDrivers')) {
                $cachedriverLoader = new RokCommon_Cache_DriverLoader();
                RokCommon_ClassLoader::registerLoader('CacheDrivers',$cachedriverLoader);
            }
            else {
                $cachedriverLoader = RokCommon_ClassLoader::getLoader('CacheDrivers');
            }
        }
        catch(Exception $le){
            throw $le;
        }

        try {
            $cachedriverLoader->addDriverPath($path);
        }
        catch(RokCommon_Cache_Exception $ce){
            throw $ce;
        }
    }

	/**
	 * Constructor
	 *
	 * @param int $defaultLifeTime Default cache lifetime in seconds
	 * @return void
	 */
	public function __construct($defaultLifeTime=0)
	{
		if(is_numeric($defaultLifeTime) && $defaultLifeTime>0) $this->defaultLifeTime=$defaultLifeTime;
	}

	/**
	 * Short description of method addDriver
	 *
	 * @param string $name Name of driver strategy
	 * @param CacheDriver $driver Driver strategy
	 * @param boolean $default Default strategy
	 * @return boolean
	 */
	public function addDriver($name,  RokCommon_Cache_Driver &$driver, $default = TRUE)
	{
		if(isset($this->drivers[$name])) return false;

		$this->drivers[$name]=$driver;
		if($default) $this->defaultDriver=$name;
		return true;
	}

	/**
	 * Gets driver strategy
	 *
	 * @param string $name Name of driver strategy
	 * @throws RokCommon_Cache_Exception
	 * @return CacheDriver
	 */
	protected function getDriver($name=NULL){
		if(empty($name) || !array_key_exists($name, $this->drivers)) $name=$this->defaultDriver;
		else return $this->drivers[$name];

		if(empty($name) || !array_key_exists($name, $this->drivers))
		foreach($this->drivers as $drvName=>$driver) {
			return $this->drivers[$drvName];
		}
		else return $this->drivers[$name];

		throw new RokCommon_Cache_Exception('No driver strategy set!');
	}

	/**
	 * Save data to cache
	 *
	 * @param string $groupName Name of group of cache
	 * @param string $identifier Identifier of data - it should be unique in group
	 * @param mixed $data Data
	 * @param string $driver Driver strategy
	 * @throws RokCommon_Cache_Exception
	 * @return boolean
	 */
	public function set($groupName, $identifier,  $data, $driver = NULL)
	{
		try{
			return $this->getDriver($driver)->set($groupName, $identifier, serialize($data));
		}
		catch (RokCommon_Cache_Exception $e){
			if($this->debugMode) throw $e;
			else return false;
		}
	}

	/**
	 * Gets data from cache
	 *
	 * @param string $groupName Name of group
	 * @param string $identifier Identifier of data
	 * @param string $driver Driver strategy
	 * @throws RokCommon_Cache_Exception
	 * @return mixed
	 */
	public function get($groupName, $identifier, $driver = NULL)
	{
		try{
			$drv=$this->getDriver($driver);
			if(!$drv->exists($groupName, $identifier)) return false;
			$data=$drv->get($groupName, $identifier);
			if($data===false) return false;
			return unserialize($data);
		}
		catch (RokCommon_Cache_Exception $e){
			if($this->debugMode) throw $e;
			else return false;
		}
	}

	/**
	 * Clears all cache generated by this class with one/all drivers
	 *
	 * @param string $driver Name of driver strategy
	 * @return boolean
	 */
	public function clearAllCache($driver = NULL)
	{
		try{
			if(empty($driver) || !array_key_exists($driver, $this->drivers)) {
				foreach($this->drivers as $drv) $drv->clearAllCache();
				return true;
			}
			return $this->drivers[$driver]->clearAllCache();
		}
		catch (RokCommon_Cache_Exception $e){
			if($this->debugMode) throw $e;
			else return false;
		}
	}


    /**
	 * Sets the lifetime
	 *
	 * @param string $driver Name of driver strategy
	 * @return boolean
	 */
	public function setLifeTime($lifetime, $driver = NULL)
	{
		try{
			if(empty($driver) || !array_key_exists($driver, $this->drivers)) {
				foreach($this->drivers as $drv) $drv->setLifeTime($lifetime);
				return true;
			}
			return $this->drivers[$driver]->setLifeTime($lifetime);
		}
		catch (RokCommon_Cache_Exception $e){
			if($this->debugMode) throw $e;
			else return false;
		}
	}

	/**
	 * Clears cache of specified group  with one/all drivers
	 *
	 * @param string $groupName Name of group
	 * @param string $driver Name of driver strategy
	 * @return boolean
	 */
	public function clearGroupCache($groupName, $driver = NULL)
	{
		try{
			if(empty($driver) || !array_key_exists($driver, $this->drivers)) {
				foreach($this->drivers as $drv) $drv->clearGroupCache($groupName);
				return true;
			}
			return $this->drivers[$driver]->clearGroupCache($groupName);
		}
		catch (RokCommon_Cache_Exception $e){
			if($this->debugMode) throw $e;
			else return false;
		}
	}

	/**
	 * Clears cache of specified identifier of group  with one/all drivers
	 *
	 * @param string $groupName Name of group
	 * @param string $identifier Identifier
	 * @param string $driver Name of driver strategy
	 * @return boolean
	 */
	public function clearCache($groupName, $identifier, $driver = NULL)
	{
		try{
			if(empty($driver) || !array_key_exists($driver, $this->drivers)) {
				foreach($this->drivers as $drv) $drv->clearCache($groupName,$identifier);
				return true;
			}
			return $this->drivers[$driver]->clearCache($groupName,$identifier);
		}
		catch (RokCommon_Cache_Exception $e){
			if($this->debugMode) throw $e;
			else return false;
		}
	}

	/**
	 * Turns debug mode on. Exceptions will be thrown
	 *
	 */
	public function debugModeOn(){
		$this->debugMode=true;
	}

	/**
	 * Turns debug mode off. No exceptions will be thrown
	 *
	 */
	public function debugModeOff(){
		$this->debugMode=false;
	}

} /* end of class RokCommon_Cache */


// Load the Base Commons Driver Path
RokCommon_Cache::addDriverPath(realpath(dirname(__FILE__).'/Cache/Driver'));