<?php

namespace App\ReportsData\EntityFields;

/**
 * The class caches all RD entity fields
 * @author Gabriel
 */
class Cache
{

	/**
	 * All cached values for all entities.
	 * @var array
	 */
	protected $values = [];

	/**
	 * Singleton instance.
	 * @var self
	 */
	static protected $instance;

	/**
	 * The maximum number of cached results per entity. When this number is reached, the current entity is flushed.`
	 * @var integer
	 */
	protected $maxCacheSizePerEntity = 2000;

	private function __construct()
	{ }

	/**
	 * Creates a Singleton instance.
	 * @return self
	 */
	static public function getInstance()
	{
		if (!self::$instance) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Adds a new element in the cache.
	 * @param string $entity
	 * @param string $id - mostly int but it can be string
	 * @param mixed $value - usually array of cached fields.
	 * @throws \Exception
	 */
	public function set($entity, $id, $value)
	{
		if ($value===null) {
			throw new \Exception("You cannot cache NULL for RD Entity fields classes.");
		}

		// if cache is disabled - skip the storage
		if ($this->maxCacheSizePerEntity<=0) {
			return ;
		}

		// clears the current cache if max size per entity is reached
		if ($this->values[$entity] and !$this->values[$entity][$id] and count($this->values[$entity])>=$this->maxCacheSizePerEntity) {
			$this->flushEntity($entity);
		}

		$this->values[$entity][$id] = $value;

	}

	/**
	 * Returns the cached value of a certain entity based on type and id.
	 * @param string $entity
	 * @param string $id  - mostly int but it can be string
	 */
	public function get($entity, $id)
	{
		return $this->values[$entity][$id];
	}

	/**
	 * Clears all cached values for all entities.
	 */
	public function flushAll()
	{
		$this->values = [];
	}

	/**
	 * Clears all elements of a certain entity.
	 * @param string $entity
	 */
	public function flushEntity($entity)
	{
		unset($this->values[$entity]);
	}

	/**
	 * Changes the max cache size per entity.
	 * @param Int $maxCacheSizePerEntity
	 */
	public function setMaxCacheSizePerEntity($maxCacheSizePerEntity)
	{
		$this->maxCacheSizePerEntity = $maxCacheSizePerEntity;
	}

}

