#!/usr/bin/php
<?php

if ($argc < 2) {
	fwrite(STDERR, "Usage: $argv[0] composer.json\n");
	exit(1);
}

$composer = json_decode(file_get_contents($argv[1]), true);

$autoloaders = [
	'doctrine/dbal'                     => 'Doctrine/DBAL/autoload.php',
	'doctrine/inflector'                => 'Doctrine/Common/Inflector/autoload.php',
	'dragonmantank/cron-expression'     => 'Cron/autoload.php',
	'egulias/email-validator'           => 'Egulias/EmailValidator/autoload.php',
	'illuminate/auth'                   => 'Illuminate/Auth/autoload.php',
	'illuminate/broadcasting'           => 'Illuminate/Broadcasting/autoload.php',
	'illuminate/bus'                    => 'Illuminate/Bus/autoload.php',
	'illuminate/cache'                  => 'Illuminate/Cache/autoload.php',
	'illuminate/config'                 => 'Illuminate/Config/autoload.php',
	'illuminate/console'                => 'Illuminate/Console/autoload.php',
	'illuminate/container'              => 'Illuminate/Container/autoload.php',
	'illuminate/contracts'              => 'Illuminate/Contracts/autoload.php',
	'illuminate/cookie'                 => 'Illuminate/Cookie/autoload.php',
	'illuminate/database'               => 'Illuminate/Database/autoload.php',
	'illuminate/encryption'             => 'Illuminate/Encryption/autoload.php',
	'illuminate/events'                 => 'Illuminate/Events/autoload.php',
	'illuminate/filesystem'             => 'Illuminate/Filesystem/autoload.php',
	'illuminate/hashing'                => 'Illuminate/Hashing/autoload.php',
	'illuminate/http'                   => 'Illuminate/Http/autoload.php',
	'illuminate/log'                    => 'Illuminate/Log/autoload.php',
	'illuminate/mail'                   => 'Illuminate/Mail/autoload.php',
	'illuminate/notifications'          => 'Illuminate/Notifications/autoload.php',
	'illuminate/pagination'             => 'Illuminate/Pagination/autoload.php',
	'illuminate/pipeline'               => 'Illuminate/Pipeline/autoload.php',
	'illuminate/queue'                  => 'Illuminate/Queue/autoload.php',
	'illuminate/redis'                  => 'Illuminate/Redis/autoload.php',
	'illuminate/routing'                => 'Illuminate/Routing/autoload.php',
	'illuminate/session'                => 'Illuminate/Session/autoload.php',
	'illuminate/support'                => 'Illuminate/Support/autoload.php',
	'illuminate/translation'            => 'Illuminate/Translation/autoload.php',
	'illuminate/validation'             => 'Illuminate/Validation/autoload.php',
	'illuminate/view'                   => 'Illuminate/View/autoload.php',
	'laravel/tinker'                    => 'Laravel/Tinker/autoload.php',
	'league/commonmark'                 => 'League/CommonMark/autoload.php',
	'league/flysystem'                  => 'League/Flysystem/autoload.php',
	'monolog/monolog'                   => 'Monolog/autoload.php',
	'nesbot/carbon'                     => 'Carbon/autoload.php',
	'nyholm/psr7'                       => 'Nyholm/Psr7/autoload.php',
	'opis/closure'                      => 'Opis/Closure/autoload.php',
	'psr/container'                     => 'Psr/Container/autoload.php',
	'psr/http-message'                  => 'Psr/Http/Message/autoload.php',
	'psr/log'                           => 'Psr/Log/autoload.php',
	'psr/simple-cache'                  => 'Psr/SimpleCache/autoload.php',
	'ramsey/uuid'                       => 'Ramsey/Uuid/autoload.php',
	'swiftmailer/swiftmailer'           => 'Swift/swift_required.php',
	'symfony/cache'                     => 'Symfony/Component/Cache/autoload.php',
	'symfony/console'                   => 'Symfony/Component/Console/autoload.php',
	'symfony/debug'                     => 'Symfony/Component/Debug/autoload.php',
	'symfony/finder'                    => 'Symfony/Component/Finder/autoload.php',
	'symfony/http-foundation'           => 'Symfony/Component/HttpFoundation/autoload.php',
	'symfony/http-kernel'               => 'Symfony/Component/HttpKernel/autoload.php',
	'symfony/process'                   => 'Symfony/Component/Process/autoload.php',
	'symfony/routing'                   => 'Symfony/Component/Routing/autoload.php',
	'symfony/var-dumper'                => 'Symfony/Component/VarDumper/autoload.php',
	'tijsverkoyen/css-to-inline-styles' => 'TijsVerkoyen/CssToInlineStyles/autoload.php',
	'vlucas/phpdotenv'                  => 'Dotenv/autoload.php',
];

$composer_require = $composer['require'] ?? [];

# Replaced packages
foreach ($composer['replace'] ?? [] as $package => $version) {
	# Treat "replaced" internal packages as required dependencies
	if (strpos($package, 'illuminate/') === 0)
		$composer_require[$package] = $version;
}

# Required packages
$required = [];
foreach (array_keys($composer_require) as $package) {
	# Ignore php and extensions
	if ($package === 'php' || strpos($package, 'ext-') === 0)
		continue;
	# No known autoloader
	if (!array_key_exists($package, $autoloaders)) {
		fwrite(STDERR, "Missing autoloader for required package '$package'\n");
		exit(2);
	}
	# Require autoloader
	$path = $autoloaders[$package];
	$required[] = "require_once '$path';";
}

# Suggested packages
$suggested = [];
foreach (array_keys($composer['suggest'] ?? []) as $package) {
	# Ignore php and extensions
	if ($package === 'php' || strpos($package, 'ext-') === 0)
		continue;
	# No known autoloader
	if (!array_key_exists($package, $autoloaders)) {
		$suggested[] = "# Missing: $package";
		continue;
	}
	# Try to include autoloader
	$path = $autoloaders[$package];
	$suggested[] =
		"if (stream_resolve_include_path('$path')) { include_once '$path'; }";
}

# Statically loaded files
$files = [];
foreach ($composer['autoload']['files'] ?? [] as $file) {
	$file = (strpos($file, 'src/') === 0)
		# Full path
		? "'".substr($file, strlen('src/'))."'"
		# Relative path
		: "__DIR__.'/$file'";
	$files[] = "require_once $file;";
}

# Output autoloader template
sort($required);
sort($suggested);
sort($files);
$required = implode("\n", $required);
$suggested = implode("\n", $suggested);
$files = implode("\n", $files);
echo <<<EOF
<?php

// Require
$required

// Suggest
$suggested

// Files
$files

// @codingStandardsIgnoreFile
// @codeCoverageIgnoreStart
// this is an autogenerated file - do not edit
spl_autoload_register(
    function(\$class) {
        static \$classes = null;
        if (\$classes === null) {
            \$classes = array(
                ___CLASSLIST___
            );
        }
        \$cn = strtolower(\$class);
        if (isset(\$classes[\$cn])) {
            require ___BASEDIR___\$classes[\$cn];
        }
    },
    ___EXCEPTION___,
    ___PREPEND___
);
EOF;
