<?php
/**
 * The abstract command class.
 *
 * @author     Time.ly Network Inc.
 * @since      2.0
 *
 * @package    AI1EC
 * @subpackage AI1EC.Command
 */
abstract class Ai1ec_Command {

    /**
     * @var Ai1ec_Registry_Object
     */
    protected $_registry;

    /**
     * @var Ai1ec_Request_Parser
     */
    protected $_request;

    /**
     * @var Ai1ec_Http_Response_Render_Strategy
     */
    protected $_render_strategy;

    /**
     * Public constructor.
     *
     * @param Ai1ec_Registry_Object $registry
     * @param Ai1ec_Request_Parser $request
     */
    public function __construct(
            Ai1ec_Registry_Object $registry,
            Ai1ec_Request_Parser $request
    ) {
        $this->_registry = $registry;
        $this->_request  = $request;
    }

    /**
     * Gets parameters from the request object.
     *
     * @return array|boolean
     */
    public function get_parameters() {
        $plugin = $controller = $action = null;
        $plugin     = Ai1ec_Request_Parser::get_param( 'plugin', $plugin );
        $controller = Ai1ec_Request_Parser::get_param( 'controller', $controller );
        $action     = Ai1ec_Request_Parser::get_param( 'action', $action );
        if (
            is_scalar( $plugin ) &&
            (string)AI1EC_PLUGIN_NAME === (string)$plugin &&
            null !== $controller &&
            null !== $action
        ) {
            return array(
                'controller' => $controller,
                'action'     => $action
            );
        }
        return false;

    }

    /**
     * Execute the command.
     *
     * @return void
     */
    public function execute() {
        // Set the render strategy
        $this->set_render_strategy( $this->_request );
        // get the data from the concrete implementation
        $data = $this->do_execute();
        // render it.
        $this->_render_strategy->render( $data );
    }

    /**
     * Defines whether to stop execution of command loop or not.
     *
     * @return bool True or false.
     */
    public function stop_execution() {
        return false;
    }

    /**
     * The abstract method concrete command must implement.
     *
     * Retrieve whats needed and returns it
     *
     * @return array
     */
    abstract public function do_execute();

    /**
     * Returns whether this is the command to be executed.
     *
     * I handle the logi of execution at this levele, which is not usual for
     * The front controller pattern, because othe extensions need to inject
     * logic into the resolver ( oAuth or ics export for instance )
     * and this seems to me to be the most logical way to do this.
     *
     * @return boolean
     */
    abstract public function is_this_to_execute();

    /**
     * Sets the render strategy.
     *
     * @param Ai1ec_Request_Parser $request
     */
    abstract public function set_render_strategy( Ai1ec_Request_Parser $request );
}