<?php
/**
 * core.framework
 *
 * @category   Core
 * @package    Core_Application
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 */

// parent class
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR .'..'. DIRECTORY_SEPARATOR .'Application.php';

/**
 * @category  Core
 * @package   Core_Application
 * @copyright Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license   proprietary
 */
class Core_Console_Application extends Core_Application
{
    /**
     * @var boolean
     */
    protected $_interaction;

    /**
     * @var boolean
     */
    protected $_color;

    /**
     * @var boolean
     */
    protected $_quiet = false;

    /**
     * @var boolean
     */
    protected $_verbose = false;

    /**
     * @param Core_Application $instance
     *
     * @throws RuntimeException
     * @return Core_Console_Application
     */
    static public function getInstance(Core_Application $instance = null)
    {
        if (null === self::$_instance) {
            if (null === $instance) {
                $instance = new Core_Console_Application;
            }
            parent::getInstance($instance);
        }

        // validate application runtime
        $runtime = self::$_instance->getRuntime();
        if (self::RUNTIME_CLI !== $runtime) {
            throw new RuntimeException(sprintf('Failed to get instance of console application in %s runtime', $runtime));
        }

        return self::$_instance;
    }

    /**
     * @param boolean $interaction
     *
     * @return \Core_Console_Application
     */
    public function setInteraction($interaction)
    {
        $this->_interaction = (bool) $interaction;
        return $this;
    }

    /**
     * @return boolean
     */
    public function isInteraction()
    {
        if (null === $this->_interaction) {
            // detect shell interactivity
            exec('[[ -t 0 ]]', $output, $retval);
            $this->_interaction = !$retval;
        }
        return $this->_interaction;
    }

    /**
     * @param boolean $color
     *
     * @return \Core_Console_Application
     */
    public function setColor($color)
    {
        $this->_color = (bool) $color;
        return $this;
    }

    /**
     * @return boolean
     */
    public function isColor()
    {
        if (!$this->isInteraction()) {
            return false;
        }

        if (null === $this->_color) {
            // detect terminal color capability
            $output = exec('tput colors 2> /dev/null');
            $this->_color = (bool) ($output > 2);
        }

        return $this->_color;
    }

    /**
     * @param boolean $quiet
     *
     * @return \Core_Console_Application
     */
    public function setQuiet($quiet)
    {
        $this->_quiet   = (bool) $quiet;
        $this->_verbose =      !($quiet);
        return $this;
    }

    /**
     * @return boolean
     */
    public function isQuiet()
    {
        return $this->_quiet;
    }

    /**
     * @param boolean $verbose
     *
     * @return \Core_Console_Application
     */
    public function setVerbose($verbose)
    {
        $this->_verbose = (bool) $verbose;
        $this->_quiet   =      !($verbose);
        return $this;
    }

    /**
     * @return boolean
     */
    public function isVerbose()
    {
        return $this->_verbose;
    }

    public function run($command = null)
    {
        // 1) run basic parsing to figure out which command we wish to run
        // 2) load the command and append it's command params config
        // 3) run complete parsing of

        // so
        //
        //   add options (basic)
        //   parse
        //   load command
        //   add options (command-specific)
        //   parse
        //   dispatch
        //   done
        try {
            $opts = new Zend_Console_Getopt(array(
                'quiet|q'        => 'quiet mode',
                'verbose'        => 'verbose mode',
                'interaction'    => 'interactive mode',
                'no-interaction' => 'non-interactive mode',
                'color'          => 'colored mode',
                'no-color'       => 'non-colored mode',
            ));
            $opts->parse();
        } catch (Zend_Console_Getopt_Exception $e) {
//            echo $e->getUsageMessage();
//            exit;
        }
        $options = array();
        foreach ($opts->getOptions() as $name) {
            if (preg_match('/^no-(?P<name>.+)$/', $name, $matches)) {
                // for example
                // --color means    color => true
                // --no-color means color => false
                $name           = $matches['name'];
                $options[$name] = !$opts->getOption($name);
            } else {
                $options[$name] = $opts->getOption($name);
            }
        }
        $this->setOptions($options);
        var_dump($opts->getRemainingArgs());

        // the most basic thing
        // - input -> output
        //
        // --interaction <-> --no-interaction
        //      - defaults to --interaction if in interactive shell, --no-interaction otherwise
        //
        // --color       <-> --no-color
        //      - defaults to --color if in an interactive shell and not outputing raw data (i.e. XML)
        //
        // --quiet, -q
        //      - supress all output (except exceptions which are always displayed)
        //      - defaults to false
        //
        // --verbose -v
        //      - display all output (including heading info, enviroment, routing as it happens, etc)
        //      - defaults to false
        //
        // --help, -h, help <command>
        // --version
        //
        // - params on command line
        // - inoput on STDIN (optional, detect if it's there)
        // - output to STDOUT (honor interactive, quiet, verbose, color)
        // - errors/exceptions to STDERR (custom error handler?)
        // - parse input params (keywords + params)
        // - dispatch to command
    }
}
