<?php
if ( class_exists( 'ICWP_WPSF_Render', false ) ) {
	return;
}

class ICWP_WPSF_Render extends ICWP_WPSF_Foundation {

	const TEMPLATE_ENGINE_TWIG = 0;
	const TEMPLATE_ENGINE_PHP = 1;
	const TEMPLATE_ENGINE_HTML = 2;

	/**
	 * @var ICWP_WPSF_Render
	 */
	protected static $oInstance = null;

	private function __construct() {}

	/**
	 * @return ICWP_WPSF_Render
	 */
	public static function GetInstance() {
		if ( is_null( self::$oInstance ) ) {
			self::$oInstance = new self();
		}
		return self::$oInstance;
	}

	/**
	 * @var array
	 */
	protected $aRenderVars;

	/**
	 * @var string
	 */
	protected $sTemplatePath;

	/**
	 * @var string
	 */
	protected $sAutoloaderPath;

	/**
	 * @var string
	 */
	protected $sTemplate;

	/**
	 * @var int
	 */
	protected $nTemplateEngine;

	/**
	 * @var Twig_Environment
	 */
	protected $oTwigEnv;

	/**
	 * @var Twig_Loader_Filesystem
	 */
	protected $oTwigLoader;

	/**
	 * @return string
	 * @throws Exception
	 */
	public function render() {

		switch ( $this->getTemplateEngine() ) {

			case self::TEMPLATE_ENGINE_TWIG :
				$sOutput = $this->renderTwig();
				break;

			case self::TEMPLATE_ENGINE_HTML :
				$sOutput = $this->renderHtml();
				break;

			default:
				$sOutput = $this->renderPhp();
				break;
		}
		return $sOutput;
	}

	/**
	 * @return string
	 */
	private function renderHtml() {
		ob_start();
		@include( $this->getTemplateRoot().ltrim( $this->getTemplate(), DIRECTORY_SEPARATOR ) );
		return ob_get_clean();
	}

	/**
	 * @return string
	 */
	private function renderPhp() {
		if ( count( $this->getRenderVars() ) > 0 ) {
			extract( $this->getRenderVars() );
		}

		$sTemplate = $this->getTemplateRoot().ltrim( $this->getTemplate(), DIRECTORY_SEPARATOR );
		if ( $this->loadFS()->isFile( $sTemplate ) ) {
			ob_start();
			include( $sTemplate );
			$sContents = ob_get_clean();
		}
		else {
			$sContents = 'Error: Template file not found: '.$sTemplate;
		}

		return $sContents;
	}

	/**
	 * @deprecated
	 * @return string
	 * @throws Exception
	 */
	private function renderTwig() {
//			throw new Exception( 'Twig codebase has been removed since version 5.3.3. Render using PHP instead.' );
		$oTwig = $this->getTwigEnvironment();
		return $oTwig->render( $this->getTemplate(), $this->getRenderVars() );
	}

	/**
	 */
	public function display() {
		echo $this->render();
		return $this;
	}

	/**
	 */
	protected function autoload() {
		if ( !class_exists( 'Twig_Autoloader', false ) ) {
			require_once( $this->sAutoloaderPath );
			Twig_Autoloader::register();
		}
	}

	/**
	 * @return $this
	 */
	public function clearRenderVars() {
		return $this->setRenderVars( array() );
	}

	/**
	 * @return Twig_Environment
	 */
	protected function getTwigEnvironment() {
		if ( !isset( $this->oTwigEnv ) ) {
			self::loadAutoload();
			$this->oTwigEnv = new Twig_Environment( $this->getTwigLoader(),
				array(
					'debug' => true,
					'strict_variables' => true,
				)
			);
		}
		return $this->oTwigEnv;
	}

	/**
	 * @return Twig_Loader_Filesystem
	 */
	protected function getTwigLoader() {
		if ( !isset( $this->oTwigLoader ) ) {
			$this->oTwigLoader = new Twig_Loader_Filesystem( $this->getTemplateRoot() );
		}
		return $this->oTwigLoader;
	}

	/**
	 * @return string
	 */
	public function getTemplate() {
		$this->sTemplate = $this->loadDataProcessor()
								->addExtensionToFilePath( $this->sTemplate, $this->getEngineStub() );
		return $this->sTemplate;
	}

	/**
	 * @return int
	 */
	public function getTemplateEngine() {
		if ( !isset( $this->nTemplateEngine )
			 || !in_array( $this->nTemplateEngine, array(
				self::TEMPLATE_ENGINE_TWIG,
				self::TEMPLATE_ENGINE_PHP,
				self::TEMPLATE_ENGINE_HTML
			) ) ) {
			$this->nTemplateEngine = self::TEMPLATE_ENGINE_PHP;
		}
		return $this->nTemplateEngine;
	}

	/**
	 * @param string $sTemplate
	 * @return string
	 */
	public function getTemplateExists( $sTemplate = '' ) {
		$sFullPath = $this->getTemplateFullPath( $sTemplate );
		return $this->loadFS()->exists( $sFullPath );
	}

	/**
	 * @param string $sTemplate
	 * @return string
	 */
	public function getTemplateFullPath( $sTemplate = '' ) {
		if ( empty( $sTemplate ) ) {
			$sTemplate = $this->getTemplate();
		}
		$sTemplate = $this->loadDataProcessor()->addExtensionToFilePath( $sTemplate, $this->getEngineStub() );
		return path_join( $this->getTemplateRoot(), $sTemplate );
	}

	/**
	 * @return string
	 */
	public function getTemplateRoot() {
		$sPath = rtrim( $this->sTemplatePath, DIRECTORY_SEPARATOR );
		$sStub = $this->getEngineStub();
		if ( !preg_match( sprintf( '#%s$#', $sStub ), $sPath ) ) {
			$sPath = $sPath.DIRECTORY_SEPARATOR.$sStub;
		}
		return $sPath.DIRECTORY_SEPARATOR;
	}

	/**
	 * @return array
	 */
	public function getRenderVars() {
		return $this->aRenderVars;
	}

	/**
	 * @param array $aVars
	 * @return $this
	 */
	public function setRenderVars( $aVars ) {
		$this->aRenderVars = $aVars;
		return $this;
	}

	/**
	 * @param string $sPath
	 * @return $this
	 */
	public function setAutoloaderPath( $sPath ) {
		$this->sAutoloaderPath = $sPath;
		return $this;
	}

	/**
	 * @param string $sPath
	 * @return $this
	 */
	public function setTemplate( $sPath ) {
//			if ( !preg_match( '#\.twig$#', $sPath ) ) {
//				$sPath = $sPath . '.twig';
//			}
		$this->sTemplate = $sPath;
		return $this;
	}

	/**
	 * @return $this
	 */
	public function setTemplateEngineHtml() {
		return $this->setTemplateEngine( self::TEMPLATE_ENGINE_HTML );
	}

	/**
	 * @return $this
	 */
	public function setTemplateEnginePhp() {
		return $this->setTemplateEngine( self::TEMPLATE_ENGINE_PHP );
	}

	/**
	 * @return $this
	 */
	public function setTemplateEngineTwig() {
		return $this->setTemplateEngine( self::TEMPLATE_ENGINE_TWIG );
	}

	/**
	 * @param int $nEngine
	 * @return $this
	 */
	protected function setTemplateEngine( $nEngine ) {
		$this->nTemplateEngine = $nEngine;
		return $this;
	}

	/**
	 * @param string $sPath
	 * @return $this
	 */
	public function setTemplateRoot( $sPath ) {
		$this->sTemplatePath = $sPath;
		return $this;
	}

	/**
	 * @return string
	 */
	private function getEngineStub() {
		switch ( $this->getTemplateEngine() ) {

			case self::TEMPLATE_ENGINE_TWIG:
				$sStub = 'twig';
				break;

			case self::TEMPLATE_ENGINE_HTML:
				$sStub = 'html';
				break;

			case self::TEMPLATE_ENGINE_PHP:
				$sStub = 'php';
				break;

			default:
				$sStub = 'php';
				break;
		}
		return $sStub;
	}
}