<?php
/**
 * @copyright NetMonsters <team@netmonsters.ru>
 * @link http://netmonsters.ru
 * @package Majestic
 * @subpackage App
 * @since 27.06.12
 *
 */

/**
 * @desc CliController (run cli_class, end profiler)
 * @author Aleksandr Demidov
 */
class CliController
{
    /**
     * @var CliController
     */
    protected static $instance;

    protected $error_stream;

    protected function __construct()
    {
        ErrorHandler::init();
        $this->error_stream = Config::get('ErrorStream', 'php://stderr');
    }

    /**
     * Refuse cloning
     * @codeCoverageIgnoreStart
     */
    private function __clone()
    {
    }

    /**
     * @codeCoverageIgnoreEnd
     */

    /**
     * @static
     * @return CliController
     */
    public static function getInstance()
    {
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * @param iCli|string $cli
     * @throws ErrorException|GeneralException
     */
    public function execute($cli)
    {
        try {
            if (is_string($cli)) {
                if (!class_exists($cli)) {
                    throw new GeneralException('Action class "' . $cli . '" not found.');
                }
                $cli = new $cli;
            }
            if (!in_array('iCli', class_implements($cli))) {
                throw new ErrorException('Runner "' . get_class($cli) . '" need implement of "iCli" interface.');
            }
            $cli->run();
            if (Config::get('PROFILER')) {
                $profile = Profiler::getInstance()->getCli();
                if (Config::get('LOGGING')) {
                    Logger::getInstance()->log($profile);
                } else {
                    echo $profile;
                }
            }
        }
        catch (Exception $e) {
            $code = $e->getCode();
            if ($e instanceof ErrorException) {
                $code = $e->getSeverity();
            }
            file_put_contents($this->error_stream, PHP_EOL . 'Error ' . '#' . $code . ': ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
            file_put_contents($this->error_stream, PHP_EOL . 'Stack trace: ' . PHP_EOL . $e->getTraceAsString() . PHP_EOL, FILE_APPEND);
        }
    }
}