<?php

namespace OfficeBrain\Bundle\CacheBundle\Listener;

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;

use OfficeBrain\Bundle\CacheBundle\Setting\ServerSideCacheSetting;
use OfficeBrain\Bundle\CacheBundle\Setting\WebClientResponseCacheSetting;

	/**
	 * Request listener for serving response from cache
	 * 
	 * Response listener for caching response to cache
	 *
	 * @author OfficeBrain 4074 <info@officebrain.com>
	 *
	 */
	class ServerSideCacheListener
	{
	    public function __construct(Kernel $kernel, $cacheService=null)
	    {
	    	$this->cacheKey = null;
	    	$this->cacheService = $cacheService;
	    	$this->kernel = $kernel;
	    	$this->host = null;
	    	$this->event = null;
	    	$this->userId = null;
	    	$this->locale = null;
	    	$this->request = null;
	    	$this->response = null;
	    	$this->environment = null;
	    }

	    public function __destruct()
	    {
	    	unset($this->host);
	    	unset($this->kernel);
	    	unset($this->userId);
	    	unset($this->locale);
	    	unset($this->request);
	    	unset($this->response);
	    	unset($this->cacheKey);
	    	unset($this->cacheService);
	    	unset($this->environment);
	    }

	    /**
	     * Request listener for serving response from cache
	     *
	     * @param GetResponseEvent $event
	     * 
	     * @author OfficeBrain 4074 <info@officebrain.com>
	     * 
	     */
	    public function onKernelRequestGetFromCache($event)
	    {
	    	if($this->cacheService != null && $this->cacheService->isCacheEnabled('WEB_CLIENT_RESPONSE')) {
	    		$this->init($event);

		    	if($this->isCacheEnabledForRequest()) {
		    		$this->initCacheSetting();
		    		$responseContent = $this->cacheService->get($this->cacheKey);
		        	if ($this->cacheService->exist($this->cacheKey)) {
		        		$response = new Response();
		        		$response->setContent($responseContent);
		        		$response->send();
		        		$this->kernel->terminate($this->request, $response);
		        		unset($response);
		        		exit;
	        		}
		    	}
	    	}
		}

	    /**
	     * Response listener for caching response to cache
	     *
	     * @param GetResponseEvent $event
	     * 
	     * @author OfficeBrain 4074 <info@officebrain.com>
	     * 
	     */
	    public function onKernelResponseSaveToCache($event)
	    {
	    	if($this->cacheService != null && $this->cacheService->isCacheEnabled('WEB_CLIENT_RESPONSE')) {
		    	$this->init($event);
		    	
		    	if($this->isCacheEnabledForRequest() && !$this->response->isRedirection() && Response::HTTP_OK == $this->response->getStatusCode()) {
			        $this->initCacheSetting();
			        $responseContent = $this->response->getContent();
			        
		        	if ($this->cacheKey != null && $responseContent!='') {
		        		$this->cacheService->set($this->cacheKey, $responseContent, WebClientResponseCacheSetting::$CACHE_TTL);
		        	}

		        	unset($responseContent);
		    	}
	    	}
		}

		/**
		 * Private function to initialize the cache related variables 
		 * 
		 * @param $event
		 * 
		 * @author OfficeBrain 4074 <info@officebrain.com>
		 * 
		 */
		private function init($event)
		{
			if($event->getRequest()->get('cacheKey', null)) {
				$this->event = $event;
				$this->request = $event->getRequest();
				$this->response = $event->getResponse();
				$this->locale = $this->request->getLocale();
				$this->environment = $this->kernel->getEnvironment();
				$this->cacheKey = $this->request->get('cacheKey', null);
				$this->userId = $this->request->getSession()->get('userId', null);
				$this->host = (isset($_SERVER['HTTP_X_FORWARDED_HOST']) && $_SERVER['HTTP_X_FORWARDED_HOST']!='')?$_SERVER['HTTP_X_FORWARDED_HOST']:$this->request->getHost();
			}
		}

		/**
		 * Private function to check cache is enabled for host or not
		 *
		 * 
		 * @return true if cache is enabled for host else false
		 *
		 * @author OfficeBrain 4074 <info@officebrain.com>
		 * 
		 */
		private function isCacheEnabledForRequest()
		{
			return ($this->cacheKey != null && $this->request->isMethod('GET'));
		}

		/**
		 * Private function to prepare the cache key and initialize the cache db
		 *
		 * @author OfficeBrain 4074 <info@officebrain.com>
		 */
		private function initCacheSetting()
		{
			$cacheKeyArray = array();
			$cacheKeyArray[] = $this->host;

			if($this->userId != null) {
				$cacheKeyArray[] = $this->userId;
			}
			
			if($this->request->isXmlHttpRequest()) {
				$cacheKeyArray[] = 'ajax';
			}
			
			$cacheKeyArray[] = $this->environment;
			$cacheKeyArray[] = $this->locale;
			$cacheKeyArray[] = $this->cacheKey;
			$this->cacheKey = implode(ServerSideCacheSetting::$CACHE_KEY_SEPARATOR, $cacheKeyArray);
			$this->cacheService->selectDb('page');

			unset($cacheKeyArray);
		}
	}
