<?php
define('COMMIT_CACHE', '.php_cs.commit-cache');

$finder = PhpCsFixer\Finder::create()
    ->exclude('vendor')
    ->exclude('node_modules')
    ->exclude('cache')
    ->files()
    ->name('*.php')
    ->in('.');

$yearRange = getGitCommitYears();

$ruleSets = ['@PSR2' => true, '@Symfony' => true];

$rules = [
    // Configuration && overrides
    'binary_operator_spaces'                    => ['align_double_arrow' => true],
    'blank_line_after_opening_tag'              => false,
    'concat_space'                              => ['spacing' => 'one'],
    'method_argument_space'                     => ['ensure_fully_multiline' => true],

    // Risky
    'is_null'                                   => ['use_yoda_style' => false],
    'non_printable_character'                   => ['use_escape_sequences_in_strings' => true],

    // Safe
    'align_multiline_comment'                   => true,
    'array_syntax'                              => ['syntax' => 'short'],
    'general_phpdoc_annotation_remove'          => ['annotations' => ['author', 'package']],
    'no_multiline_whitespace_before_semicolons' => true,
    'no_useless_else'                           => true,
    'no_useless_return'                         => true,
    'ordered_imports'                           => true,
    'phpdoc_add_missing_param_annotation'       => true,
    'phpdoc_annotation_without_dot'             => true,
    'phpdoc_order'                              => true,
    'semicolon_after_instruction'               => true,
    'yoda_style'                                => false,

    'header_comment' => [
        'commentType' => 'comment',
        'location'    => 'after_declare_strict',
        'separate'    => 'bottom',
        'header'      => <<<HEADER
Copyright (C) $yearRange IRSTEA
All rights reserved.
HEADER
        ,
    ],
];

$phpVersion = findComposerPhpReq();

if ($phpVersion >= 5.6) {
    $ruleSets['@PHP56Migration'] = true;
}
if ($phpVersion >= 7.0) {
    $ruleSets['@PHP70Migration'] = true;
    $rules['declare_strict_types'] = true;
}
if ($phpVersion >= 7.1) {
    $ruleSets['@PHP71Migration'] = true;
}

echo "Rulesets: " . implode(', ', array_keys($ruleSets)) . ".\n";

return PhpCsFixer\Config::create()
  ->setRiskyAllowed(true)
  ->setUsingCache(false)
  ->setIndent('    ')
  ->setLineEnding("\n")
  ->setRules(array_merge($ruleSets, $rules))
  ->setFinder($finder);

/**
 * @return string
 */
function getGitCommitYears(): string
{
    return getCachedValue('years', function () {
        echo "Examining git history...\n";
        $last = date('Y');
        $first = exec('git log --format=%cd --date=format:%Y --date-order | tail -n1') ?? $last;
        return (null !== $last && $last !== $first) ? "$first-$last" : $first;
    });
}

/**
 * @return float
 */
function findComposerPhpReq()
{
    return getCachedValue('php-req', function () {
        if (file_exists('composer.json')) {
            $data = json_decode(file_get_contents('composer.json'), true);
            if (is_array($data) && isset($data['require']['php'])) {
                if (preg_match('/(?:>=?|\^|~)\s*([57]\.[0-9])/', $data['require']['php'], $groups)) {
                    return (float) $groups[1];
                }
            }
        }

        return 5.6;
    });
}

/**
 * @param string   $key
 * @param callable $produce
 *
 * @return string|int|bool|array
 */
function getCachedValue($key, $produce)
{
    static $commit = null;
    if (null === $commit) {
        $commit = trim(`git rev-parse HEAD`);
    }
    if (file_exists(COMMIT_CACHE) && filemtime(COMMIT_CACHE) >= filemtime(__FILE__)) {
        $cache = json_decode(file_get_contents(COMMIT_CACHE), true);
    } else {
        $cache = [];
    }
    if (!isset($cache[$commit][$key])) {
        if (!isset($cache[$commit])) {
            $cache[$commit] = [];
        }
        $cache[$commit][$key] = $produce();
        file_put_contents(COMMIT_CACHE, json_encode($cache));
    }

    return $cache[$commit][$key];
}

// vim:filetype=php