#!/usr/bin/env php
<?php

use UnitTester\Test;
use UnitTester\TestSuite;
use UnitTester\TestRunner;

$vendorAutoloadPrefixes = ['/vendor/', '/../vendor/', '/../../'];
$autoloadPath = null;

foreach ($vendorAutoloadPrefixes as $prefix)
{
    $tempAutoloadPath = __DIR__ . $prefix . 'autoload.php';

    if (file_exists($tempAutoloadPath))
    {
        $autoloadPath = $tempAutoloadPath;
        break;
    }
}

if (is_null($autoloadPath))
{
    echo 'Composer autoload file could not be found. Run the following command:' . PHP_EOL;
    echo '    composer install' . PHP_EOL;

    die();
}

require_once $autoloadPath;

$composerClassLoaderClass = new ReflectionClass(\Composer\Autoload\ClassLoader::class);
$rootDirectory = dirname(dirname(dirname($composerClassLoaderClass->getFileName())));

$defaultTestsDirectory = $rootDirectory . '/tests';

if (!is_dir($defaultTestsDirectory)) 
{
    echo 'Tests directory could not be found: ' . $defaultTestsDirectory . PHP_EOL;
    die();
}

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($defaultTestsDirectory), RecursiveIteratorIterator::SELF_FIRST);
$testFiles = [];

foreach ($objects as $fileInfo)
{
    if (!is_dir($fileInfo))
    {
        $className = basename($fileInfo->getFileName(), '.php');

        $fileName = $fileInfo->getPathName();

        if (!\class_exists($className, false)) 
        {
            $loadedClasses = \get_declared_classes();

            require_once $fileName;

            $loadedClasses = \array_values(\array_diff(\get_declared_classes(), $loadedClasses));
        }

        if (!\class_exists($className, false) && !empty($loadedClasses)) 
        {
            $offset = 0 - \strlen($className);

            foreach ($loadedClasses as $loadedClassName) {
                $reflectionClass = new ReflectionClass($loadedClassName);

                if (\substr($loadedClassName, $offset) === $className &&
                    $reflectionClass->getFileName() == $fileName) 
                {
                    $className = $loadedClassName;
                    break;
                }
            }
        }

        $testClass = new $className();

        if ($testClass instanceOf Test)
        {
            $testFiles[] = $testClass;
        }
    }
}

if (count($testFiles) == 0)
{
    echo 'No test files found' . PHP_EOL;
    return;
}

$defaultTestSuite = new TestSuite('Default Test Suite');

$options = $argv;
array_shift($options);

$singleTestOverride = null;
$singleTestMethodOverride = null;

if (count($options) > 0)
{
    foreach ($options as $option)
    {
        array_shift($options);

        if ($option == '--test')
        {
            $optionValue = (isset($options[0]) ? $options[0] : null);
            if (!is_null($optionValue))
            {
                $testParts = explode('#', $optionValue);
                $singleTestOverride = $testParts[0];
    
                if (isset($testParts[1]))
                {
                    $singleTestMethodOverride = $testParts[1];
                }
            }
        }
    }
}

/** @var Test $test */
foreach ($testFiles as $test)
{
    if (!is_null($singleTestOverride))
    {
        if ($test->getClassName() == $singleTestOverride)
        {
            if (!is_null($singleTestMethodOverride))
            {
                $test->setTestCaseFilters([$singleTestMethodOverride]);
            }
            
            $defaultTestSuite->addTest($test);
        }
    }
    else
    {
        $defaultTestSuite->addTest($test);
    }
}

$testRunner = new TestRunner();
$testRunner->addSuite($defaultTestSuite);
$testRunner->run();