<?php
namespace Engine\Cache;

/**
 * The class is used to manage the cache stored in local RAM (current session - available only to the current user).
 * @author Lucian Sirbu
 * 	Should take into account he total RAM used by the script, and run gc() more often when we need more RAM.
 */
class LocalMemoryLinear implements \Engine\Cache\BaseInterface
{

	private $data = [];

	private $maxItems = 30;					// the item count when the gc will kick in
	private $maxRemovedItems = 20;			// will get math-set, to 75% from maxItems. This is the number of items left when the gc is done
	private $minIntervalChecks = 10;		// will get math-set, after how many set() the gc will kick in
	private $sessionOps = 0;

	public function setStorageLimits($maxItems, $maxRemovedItems, $minIntervalChecks)
	{
		$this->maxItems = $maxItems;
		$this->maxRemovedItems = $maxRemovedItems;
		$this->minIntervalChecks = $minIntervalChecks;
	}

	/**
	 * Sets a value in the cache for a certain key.
	 * @param String $key
	 * @param Mixed $value
	 * @param String $expireTime
	 */
	public function set($key, $value, $expireTime=0) :void
	{
		// if key is not set
		if (!$key) {
			return ;
		}

		// do not store 'null' values
		if ($value===null) {
			return ;
		}

		$this->sessionOps++;
		if ($this->sessionOps > $this->minIntervalChecks){
			if(count($this->data) > $this->maxItems){
				$this->data = array_slice($this->data, -1*$this->maxRemovedItems);
			}

			// reset the internal counter
			$this->sessionOps = 0;
		}

		if (is_object($value)) {
			$this->data[$key] = [
				'data'=>	&$value,
			];
		}
		else {
			$this->data[$key] = [
				'data'=>	$value,
			];
		}
	}

	/**
	 * Gets a value stored in the cache for a certain key.
	 * @param String $key
	 * @return Mixed - the stored value or null if the key was not found
	 */
	public function get($key)
	{
		if (isset($this->data[$key])) {
			return $this->data[$key]['data'];
		}

		return null;
	}

	/**
	 * Deletes the value stored in the cache for a certain key.
	 * @param String $key
	 * @return Boolean - indicating if the key was correctly deleted in the cache
	 */
	public function delete($key) :void
	{
		unset($this->data[$key]);
	}

	/**
	 * Deletes the whole cache content.
	 * @return Boolean - indicating if the cache was completely destroyed
	 * @see \Engine\Cache\BaseInterface::flush()
	 */
	public function flush() :bool
	{
		$this->data = [];
		return true;
	}

	/**
	 * Returns an associative array of details for a certain key.
	 * @return Array
	 */
	public function getInfo($key)
	{
		$return = [
			'exists' => 	array_key_exists($key, $this->data),
			'key' => 		$key,
			'lastGet' => 	null,
			'hits' => 		null,
		];
		return $return;
	}
}
