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

declare(strict_types=1);

use PedroTroller\CS\Fixer\AbstractFixer;
use PedroTroller\CS\Fixer\Fixers;
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
use PhpCsFixer\FixerConfiguration\FixerOptionInterface;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\Tokenizer\Tokens;
use SebastianBergmann\Diff\Differ;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;

include sprintf('%s/../vendor/autoload.php', __DIR__);

include 'Utils.php';

$fixers = array_map(static function (AbstractFixer $fixer) {
    $samples = $fixer->getDefinition()->getCodeSamples();

    return [
        'name' => $fixer->getName(),
        'doc'  => [
            'summary' => $fixer->getDefinition()->getSummary(),
        ],
        'deprecated'  => $fixer->isDeprecated(),
        'replacement' => $fixer->getDeprecationReplacement(),
        'options'     => array_map(
            static function (FixerOptionInterface $option) {
                return [
                    'name'          => $option->getName(),
                    'description'   => $option->getDescription(),
                    'required'      => false === $option->hasDefault(),
                    'allowedValues' => $option->getAllowedValues(),
                    'allowedTypes'  => $option->getAllowedTypes(),
                    'defaultValue'  => $option->getDefault(),
                ];
            },
            $fixer instanceof ConfigurableFixerInterface
                ? $fixer->getConfigurationDefinition()->getOptions()
                : []
        ),
        'samples' => array_map(static function (CodeSample $sample) use ($fixer) {
            if ($fixer instanceof ConfigurableFixerInterface) {
                $fixer->configure($sample->getConfiguration());
            }

            $tokens = Tokens::fromCode($fixer->getSampleCode());
            $differ = new Differ();

            if ($fixer->isCandidate($tokens)) {
                $fixer->fix(new SplFileInfo(__FILE__), $tokens);
                $diff = explode("\n", $differ->diff($fixer->getSampleCode(), $tokens->generateCode()));

                foreach ($diff as $num => $line) {
                    if (strlen($line) > 80 + 1) {
                        continue;
                    }

                    while (strlen($line) < 80 + 1) {
                        $line .= ' ';
                    }

                    if (0 === $num) {
                        $line .= '// 80 chars';
                    } else {
                        $line .= '//';
                    }

                    $diff[$num] = $line;
                }
            } else {
                $diff = ['+ Fixing not supported by your PHP version.'];
            }

            return [
                'diff'          => implode("\n", $diff),
                'configuration' => $sample->getConfiguration()
                    ? Utils::arrayToString($sample->getConfiguration())
                    : [],
            ];
        }, $samples),
    ];
}, [...(new Fixers())]);

$loader = new FilesystemLoader([__DIR__]);
$twig   = new Environment($loader);

echo $twig->render('doc.twig', ['fixers' => json_decode(json_encode($fixers))]);
