<?php
namespace ModulesAbstract\FluxRest;

/**
 * Automatically manage session state between requests, to avoid time-consuming re-authentications
 * This eases the implementation of case #2 from the parent class
 * @author Lucian Sirbu
 */
class FluXEmulatorWithAutomaticSessionManagement extends FluXEmulator
{
	/**
	 * The cache/storage class
	 * @var \Engine\Cache\BaseInterface
	 */
	protected $storage = null;

	/**
	 * The application token, sent when authenticating, internally intercepted on authentication requests
	 * @var string
	 */
	protected $applicationToken = null;


	/**
	 * The authentication token.
	 * @var string
	 */
	protected $authenticationToken = null;

	/**
	 * Set the storage object
	 * @param \Engine\Cache\BaseInterface $storage
	 * @return \ModulesAbstract\FluxRest\FluXEmulatorWithAutomaticSessionManagement
	 */
	public function setStorageObj($storage)
	{
		$this->storage = $storage;
		return $this;
	}

	/**
	 * Restore internal state from the cache, if possible
	 * @return boolean
	 */
	public function restore()
	{
		$cacheKey = sprintf("%s:%s", __CLASS__, $this->wsEndpoint);

		$internalState = $this->storage->get($cacheKey);
		if ($internalState && $internalState['serverSentVars'] && $internalState['applicationToken']) {

			$this->serverSentVars = 		$internalState['serverSentVars'];

			$this->instanceSessionId = 		$internalState['instanceSessionId'];
			$this->agent = 					$internalState['agent'];
			$this->authenticationToken = 	$internalState['authenticationToken'];
			$this->applicationToken = 		$internalState['applicationToken'];
			return true;
		}

		return false;
	}

	/**
	 * Save the internal state to the cache
	 */
	public function save()
	{
		$cacheKey = sprintf("%s:%s", __CLASS__, $this->wsEndpoint);

		$internalState = [
			'lastAccess' => 			microtime(true),

			'serverSentVars' => 		$this->serverSentVars,

			'instanceSessionId' => 		$this->instanceSessionId,
			'agent' => 					$this->agent,
			'authenticationToken' => 	$this->authenticationToken,
			'applicationToken' => 		$this->applicationToken,
		];

		$this->storage->set($cacheKey, $internalState);
	}

	/**
	 * Intercept some calls
	 * {@inheritDoc}
	 * @see \ModulesAbstract\FluxRest\FluXEmulator::buildResponseHandler()
	 */
	protected function buildResponseHandler($rawResponse)
	{
		if ($rawResponse->action == 'Authenticate') {
			$handler = new \ModulesAbstract\FluxRest\ResponseHandler\Operation\Authenticate($this, $this->logger);
			$handler->appToken = $this->applicationToken;

			$this->authenticationToken = null;	// reset internal token, a new one will be received from TINA

			return $handler;
		}

		return parent::buildResponseHandler($rawResponse);
	}

	/**
	 * Intercept some calls
	 * {@inheritDoc}
	 * @see \ModulesAbstract\FluxRest\FluXEmulator::requestRaw()
	 */
	protected function requestRaw($request)
	{
		// intercept Authenticate calls, save the app token internally, and save it/restore it, to be able to automatically use it when needed
		if ($request->action=='Authenticate' && !$this->applicationToken) {
			$this->applicationToken = $request->appToken;
		}
		return parent::requestRaw($request);
	}
}
