<?php

class Designer_Tests_Tester
{
    private $_tests;
    private $_index;
    private $_report;
    private $_options;

    private function __construct($tests, $options)
    {
        $this->_index = -1;
        $this->_tests = $tests;
        $this->_options = $options;

        ini_set('html_errors', 0);
        register_shutdown_function(array($this, '_buildReport'));
        set_error_handler(array($this, '_errorHandler'));
    }

    public static function run($tests, $options = array())
    {
        $tester = new Designer_Tests_Tester($tests, $options);
        $tester->execute();
    }

    private function execute()
    {
        $this->_report = new ArrayObject();
        for ($this->_index = 0; $this->_index < count($this->_tests); $this->_index++) {
            $this->_tests[$this->_index]->run($this->_report);
        }
        $this->_index = -1;
    }

    /**
     * Build test session report.
     */
    public function _buildReport()
    {
        ob_start();
        if (isset($this->_options['format']) && 'json' === $this->_options['format']) {
            echo json_encode($this->_report);
        } else {
            if (count($this->_report)) {
                echo "<tests>\n";
                foreach ($this->_report as $info) {
                    echo '    <test name="' . $info['name'] . '" assertions="' . $info['assertions']
                        . '" status="' . $info['status'] . '"';
                    if (!empty($info['output'])) {
                        echo ">\n        <![CDATA[" . $info['output'] . "]]>\n    </test>";
                    } else {
                        echo ' />';
                    }
                    echo "\n";
                }
                echo '</tests>';
            } else
                echo '<tests />';
        }
        $content = ob_get_clean();
        if (isset($this->_options['outputToFile']) && $this->_options['outputToFile']) {
            file_put_contents(dirname(__FILE__) . 'tests_result.xml', $content);
        } else {
            echo $content;
        }

    }

    function _errorHandler($errno, $errstr, $errfile, $errline, $errcontext)
    {
        throw new Exception('ERROR: ' . $errfile . ' (' . $errline . '): '
            . $errstr);
    }
}
