<?php
namespace SabaiApps\Directories;

use SabaiApps\Framework\Application\IController;
use SabaiApps\Framework\Application\AbstractApplication;
use SabaiApps\Framework\Application\AbstractRoutingController as FrameworkAbstractRoutingController;
use SabaiApps\Framework\Application\Context as FrameworkContext;

/**
 * Base Controller class for application controllers.
 * Provides methods for setting application, parent controller, route, and executing controller logic.
 * Also provides magic methods for accessing components and delegating method calls to the application.
 *
 * @method Platform\AbstractPlatform getPlatform()
 * @method \SabaiApps\Framework\DB\AbstractDB getDB()
 */
abstract class Controller implements IController {

	/**
	 * @var AbstractApplication Reference to the application instance.
	 */
	protected $_application;
	/**
	 * @var FrameworkAbstractRoutingController Reference to the parent routing controller.
	 */
	protected $_parent;
	/**
	 * @var mixed Route information for the controller.
	 */
	protected $_route;

	/**
	 * Sets the route for the controller.
	 *
	 * @param mixed $route
	 * @return $this
	 */
	public function setRoute( $route ) {
		$this->_route = $route;

		return $this;
	}

	/**
	 * Sets the application instance.
	 *
	 * @param AbstractApplication $application
	 * @return $this
	 */
	final public function setApplication( AbstractApplication $application ) {
		$this->_application = $application;

		return $this;
	}

	/**
	 * Gets the application instance.
	 *
	 * @return AbstractApplication
	 */
	final public function getApplication() {
		return $this->_application;
	}

	/**
	 * Sets the parent routing controller.
	 *
	 * @param FrameworkAbstractRoutingController $controller
	 * @return $this
	 */
	final public function setParent( FrameworkAbstractRoutingController $controller ) {
		$this->_parent = $controller;

		return $this;
	}

	/**
	 * Executes the controller logic.
	 *
	 * @param FrameworkContext $context
	 */
	final public function execute( FrameworkContext $context ) {
		$this->_doExecute( $context );
	}

	/**
	 * Magic method to delegate method calls to the application instance.
	 *
	 * @param string $method
	 * @param array  $args
	 * @return mixed
	 */
	final public function __call( $method, $args ) {
		return call_user_func_array( array( $this->_application, $method ), $args );
	}

	/**
	 * Magic getter to access components as properties.
	 *
	 * @param string $name
	 * @return mixed
	 */
	final public function __get( $name ) {
		return $this->_application->getComponent( $name );
	}

	/**
	 * Checks the CSRF token for a request.
	 *
	 * @param Context $context
	 * @param string  $tokenId
	 * @param bool    $reuseable
	 * @param string  $tokenName
	 * @return bool
	 */
	protected function _checkToken( Context $context, $tokenId, $reuseable = false, $tokenName = Request::PARAM_TOKEN ) {
		if ( ! $token = $context->getRequest()->asStr( $tokenName, false ) ) {
			$context->setBadRequestError();
			return false;
		}
		if ( ! $this->_application->Form_Form_validateToken( $token, $tokenId, $reuseable ) ) {
			$context->setTokenExpiredError();
			return false;
		}
		return true;
	}

	/**
	 * Abstract method to be implemented by subclasses for controller execution logic.
	 *
	 * @param Context $context
	 */
	abstract protected function _doExecute( Context $context );
}
