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

/**
 * @param string $message
 * @param integer $code
 */
function exitWithError($message, $code = 1) {
    echo $message . PHP_EOL;
    exit($code);
}

/** @var \Composer\Autoload\ClassLoader $autoloader */
// $_SERVER['argv'][0] contains the exact command used to call this command,
$path = getenv('TYPO3_PATH_ROOT');
$pwd = rtrim($_SERVER['PWD'], '/') . '/';
$entry = $_SERVER['argv'][0];

if (!$path) {
    if (is_dir($pwd . '/vendor')) {
        // called from folder containing vendor dir - use current dir.
        $path = $pwd;
    } elseif (strpos($entry, '/') === 0) {
        // absolute path - assume that root is the folder one level above the LAST "/vendor/" segment
        $path = substr($entry, 0, strrpos($entry, '/vendor/') + 1);
    } elseif (strpos($entry, '.') === 0) {
        // relative path with dot prefix. Assume that if the path contains a "/vendor/" segment,
        // the target folder is exactly one level above that folder. If it does not, assume that
        // the root folder is exactly one level above
        $path = substr($pwd . $entry, 0, strrpos($pwd . $entry, '/vendor/') + 1);
    } elseif (strpos($entry, '.') !== 0) {
        // Path is neither absolute nor dot-prefixed, but is a relative path without prefix. Calculate the
        // path based on $pwd.$entry
        $path = substr($pwd . $entry, 0, strrpos($pwd . $entry, '/vendor/') + 1);
    } elseif (strpos($entry, '/') === false) {
        // Path is only the filename - we then only need to consider $pwd as the path to our script.
        $path = substr($pwd, 0, strrpos($pwd, '/vendor/') + 1);
    } else {
        // Fallback, assumed path - was hardcoded and only possible value in the past.
        $path = __DIR__ . '/../../../../../';
    }
}
$path = rtrim($path, '/') . '/';


$autoloader = require $path . 'vendor/autoload.php';

if (!isset($argv[1])) {
    exitWithError('You must specify at least one composer PSR-4 root namespace for which to build ViewHelpers');
}

if (!getenv('TYPO3_PATH_ROOT')) {
    putenv('TYPO3_PATH_ROOT=' . $path);
}

if (file_exists($path . 'Tests/bootstrap.php')) {
    require_once $path . 'Tests/bootstrap.php';
} else {
    \FluidTYPO3\Development\Bootstrap::initialize(
        $autoloader,
        [
            'extbase_typo3dbbackend_tablecolumns' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL,
            'extbase_typo3dbbackend_queries' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL,
            'extbase_datamapfactory_datamap' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL,
            'cache_rootline' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL,
            'cache_pages' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL,
            'cache_core' => \FluidTYPO3\Development\Bootstrap::CACHE_PHP_NULL,
            'cache_runtime' => \FluidTYPO3\Development\Bootstrap::CACHE_MEMORY,
            'extbase_object' => \FluidTYPO3\Development\Bootstrap::CACHE_MEMORY,
            'extbase_reflection' => \FluidTYPO3\Development\Bootstrap::CACHE_MEMORY,
            'l10n' => \FluidTYPO3\Development\Bootstrap::CACHE_NULL,
            'fluid_template' => \FluidTYPO3\Development\Bootstrap::CACHE_PHP_NULL
        ],
        [
            'core'
        ]
    );
}

$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);

if (!$GLOBALS['BE_USER'] ?? false) {
    $GLOBALS['BE_USER'] = $objectManager->get(\TYPO3\CMS\Core\Authentication\BackendUserAuthentication::class);
}

$namespaces = array_slice($argv, 1);
$namespaceClassPathMap = array();
$prefixes = $autoloader->getPrefixesPsr4();

foreach ($namespaces as $namespace) {
	$namespace = trim($namespace, '\\') . '\\';

	$classesPath = $prefixes[$namespace][0];
	$namespace = rtrim($namespace, '\\') . '\\ViewHelpers\\';
	$namespaceClassPathMap[$namespace] = $classesPath . '/ViewHelpers/';
	if (!is_dir($classesPath)) {
		exitWithError(sprintf('Directory "%s" does not exist but is declared in composer autoload entries', $classesPath));
	}
}


$generator = new \TYPO3\FluidSchemaGenerator\SchemaGenerator();
$xsd = $generator->generateXsd(
    $namespaceClassPathMap,
    function ($className, ...$arguments) use ($objectManager) { return $objectManager->get($className, ...$arguments); }
);

echo $xsd;
