<?php

namespace Rhymix\Framework\Drivers\Cache;

/**
 * The APC cache driver.
 */
class APC implements \Rhymix\Framework\Drivers\CacheInterface
{
	/**
	 * Set this flag to false to disable cache prefixes.
	 */
	public $prefix = true;

	/**
	 * The singleton instance is stored here.
	 */
	protected static $_instance = null;

	/**
	 * Direct invocation of the constructor is not permitted.
	 */
	protected function __construct()
	{

	}

	/**
	 * Create a new instance of the current cache driver, using the given settings.
	 *
	 * @param array $config
	 * @return void
	 */
	public static function getInstance(array $config)
	{
		if (self::$_instance === null)
		{
			self::$_instance = new self();
		}
		return self::$_instance;
	}

	/**
	 * Check if the current cache driver is supported on this server.
	 *
	 * This method returns true on success and false on failure.
	 *
	 * @return bool
	 */
	public static function isSupported()
	{
		return function_exists('apcu_exists');
	}

	/**
	 * Validate cache settings.
	 *
	 * This method returns true on success and false on failure.
	 *
	 * @param mixed $config
	 * @return bool
	 */
	public static function validateSettings($config)
	{
		return true;
	}

	/**
	 * Get the value of a key.
	 *
	 * This method returns null if the key was not found.
	 *
	 * @param string $key
	 * @return mixed
	 */
	public function get($key)
	{
		$value = apcu_fetch($key);
		return $value === false ? null : $value;
	}

	/**
	 * Set the value to a key.
	 *
	 * This method returns true on success and false on failure.
	 * $ttl is measured in seconds. If it is zero, the key should not expire.
	 *
	 * @param string $key
	 * @param mixed $value
	 * @param int $ttl
	 * @param bool $force
	 * @return bool
	 */
	public function set($key, $value, $ttl = 0, $force = false)
	{
		return apcu_store($key, $value, $ttl);
	}

	/**
	 * Delete a key.
	 *
	 * This method returns true on success and false on failure.
	 * If the key does not exist, it should return false.
	 *
	 * @param string $key
	 * @return bool
	 */
	public function delete($key)
	{
		return apcu_delete($key);
	}

	/**
	 * Check if a key exists.
	 *
	 * This method returns true on success and false on failure.
	 *
	 * @param string $key
	 * @return bool
	 */
	public function exists($key)
	{
		return apcu_exists($key);
	}

	/**
	 * Increase the value of a key by $amount.
	 *
	 * If the key does not exist, this method assumes that the current value is zero.
	 * This method returns the new value.
	 *
	 * @param string $key
	 * @param int $amount
	 * @return int
	 */
	public function incr($key, $amount)
	{
		$result = apcu_inc($key, $amount);
		if ($result === false)
		{
			apcu_store($key, $amount);
			$result = $amount;
		}
		return $result;
	}

	/**
	 * Decrease the value of a key by $amount.
	 *
	 * If the key does not exist, this method assumes that the current value is zero.
	 * This method returns the new value.
	 *
	 * @param string $key
	 * @param int $amount
	 * @return int
	 */
	public function decr($key, $amount)
	{
		$result = apcu_dec($key, $amount);
		if ($result === false)
		{
			apcu_store($key, 0 - $amount);
			$result = 0 - $amount;
		}
		return $result;
	}

	/**
	 * Clear all keys from the cache.
	 *
	 * This method returns true on success and false on failure.
	 *
	 * @return bool
	 */
	public function clear()
	{
		return apcu_clear_cache();
	}
}
