#!/usr/bin/env php
<?php
// Make sure this script is being run over the PHP CLI!
if ('cli' !== php_sapi_name()) {
	return;
}

require_once __DIR__ . '/../index.php';

use function PhpcsChanged\Cli\{
	printHelp,
	printVersion,
	printErrorAndExit,
	getDebug,
	runManualWorkflow,
	runSvnWorkflow,
	runGitWorkflow,
	reportMessagesAndExit,
	fileHasValidExtension,
	shouldIgnorePath,
	printInstalledCodingStandards
};
use PhpcsChanged\UnixShell;
use PhpcsChanged\CacheManager;
use PhpcsChanged\FileCache;

$optind = 0;
$options = getopt(
	'hsi',
	[
		'help',
		'version',
		'diff:',
		'phpcs-orig:',
		'phpcs-unmodified:',
		'phpcs-new:',
		'phpcs-modified:',
		'svn',
		'git',
		'git-unstaged',
		'git-staged',
		'git-branch:',
		'git-base:',
		'standard:',
		'report:',
		'debug',
		'ignore:',
		'cache',
		'no-cache',
		'clear-cache',
		'arc-lint',
		'always-exit-zero',
		'no-cache-git-root',
		'no-verify-git-file',
		'warning-severity:',
		'error-severity:',
	],
	$optind
);

$fileNames = array_slice($argv, $optind);
$fileNamesExpanded = [];
foreach( $fileNames as $file ) {
	if (is_dir($file)) {
		if ( shouldIgnorePath($file, $options['ignore'] ?? null, '') ) {
			continue;
		}
		$iterator = new RecursiveIteratorIterator(new RecursiveCallbackFilterIterator(new RecursiveDirectoryIterator($file, (RecursiveDirectoryIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS)), function($file, $key, $iterator){
			if ($file->isFile() && !fileHasValidExtension($file)) {
				return false;
			}
			return $iterator->hasChildren() || $file->isFile() ? true : false;
		}));
		foreach ($iterator as $file) {
			if (shouldIgnorePath($file->getPathName(), $options['ignore'] ?? null,'')) {
				continue;
			}
			$fileNamesExpanded[] = $file->getPathName();
		}
	} elseif (!shouldIgnorePath($file, $options['ignore'] ?? null, '')) {
		$fileNamesExpanded[] = $file;
	}
}

if (isset($options['h']) || isset($options['help'])) {
	printHelp();
	exit(0);
}

if (isset($options['version'])) {
	printVersion();
}

if (isset($options['i'])) {
	printInstalledCodingStandards();
}

// --git-branch exists for compatibility, --git-base supports branches
if (isset($options['git-branch'])) {
	$options['git-base'] = $options['git-branch'];
	unset($options['git-branch']);
}

// --arc-lint is a shorthand for several other options
if (isset($options['arc-lint'])) {
	$options['no-verify-git-file'] = 1;
	$options['always-exit-zero'] = 1;
	unset($options['arc-lint']);
}

if (isset($options['phpcs-orig'])) {
	$options['phpcs-unmodified'] = $options['phpcs-orig'];
	unset($options['phpcs-orig']);
}
if (isset($options['phpcs-new'])) {
	$options['phpcs-modified'] = $options['phpcs-new'];
	unset($options['phpcs-new']);
}

$debug = getDebug(isset($options['debug']));
run($options, $fileNamesExpanded, $debug);

function run(array $options, array $fileNamesExpanded, callable $debug): void {
	$debug('Running on filenames: ' . implode(', ', $fileNamesExpanded));
	$debug('Options: ' . json_encode($options));
	$reportType = $options['report'] ?? 'full';
	$diffFile = $options['diff'] ?? null;
	$phpcsUnmodifiedFile = $options['phpcs-unmodified'] ?? null;
	$phpcsModifiedFile = $options['phpcs-modified'] ?? null;

	if ($diffFile && $phpcsUnmodifiedFile && $phpcsModifiedFile) {
		reportMessagesAndExit(
			runManualWorkflow($diffFile, $phpcsUnmodifiedFile, $phpcsModifiedFile),
			$reportType,
			$options
		);
		return;
	}

	if ((isset($options['svn']) || isset($options['git'])) && empty($fileNamesExpanded)) {
		printErrorAndExit('You must supply at least one file or directory to process.');
		return;
	}

	if (isset($options['svn'])) {
		$shell = new UnixShell();
		reportMessagesAndExit(
			runSvnWorkflow($fileNamesExpanded, $options, $shell, new CacheManager(new FileCache(), $debug), $debug),
			$reportType,
			$options
		);
		return;
	}

	if (isset($options['git'])) {
		$shell = new UnixShell();
		reportMessagesAndExit(
			runGitWorkflow($fileNamesExpanded, $options, $shell, new CacheManager(new FileCache(), $debug), $debug),
			$reportType,
			$options
		);
		return;
	}

	if (count($options) > 0) {
		printErrorAndExit('You must use either manual or automatic mode.');
		return;
	}
	printHelp();
	exit(1);
}

