<?php
// this file sucks, screws up the header if incomplete
// successfully corrects filenames though
// fix this if you ever feel like it, or don't

date_default_timezone_set('utc');

function git_changes(): array {
    $files = [];

    $dir = getcwd();
    try {
        chdir(__DIR__ . '/..');

        $output = explode("\n", trim(shell_exec('git status --short --porcelain=v1 --untracked-files=all --no-column')));

        foreach($output as $line) {
            $line = trim($line);
            $file = realpath(explode(' ', $line)[1]);
            $files[] = $file;
        }

    } finally {
        chdir($dir);
    }

    return $files;
}

function collect_files(string $directory): array {
    $files = [];
    $dir = glob(realpath($directory) . DIRECTORY_SEPARATOR . '*');

    foreach($dir as $file) {
        if(is_dir($file)) {
            $files = array_merge($files, collect_files($file));
            continue;
        }

        $files[] = $file;
    }

    return $files;
}

echo 'Indexing changed files according to git...' . PHP_EOL;

$changed = git_changes();

echo 'Collecting files...' . PHP_EOL;

$sources = collect_files(__DIR__ . '/../src');
$tests = collect_files(__DIR__ . '/../tests');

$files = array_merge($sources, $tests);

$topDir = dirname(__DIR__) . DIRECTORY_SEPARATOR;

$now = date('Y-m-d');

foreach($files as $file) {
    echo 'Scanning ' . str_replace($topDir, '', $file) . '...' . PHP_EOL;

    try {
        $handle = fopen($file, 'rb');

        $checkPHP = trim(fgets($handle)) === '<?php';
        if(!$checkPHP) {
            echo 'File is not PHP.' . PHP_EOL;
            continue;
        }

        $headerLines = [];

        $expectLine = '// ' . basename($file);
        $nameLine = trim(fgets($handle));
        if($nameLine !== $expectLine) {
            echo '  File name is missing or invalid, queuing update...' . PHP_EOL;
            $headerLines['name'] = $expectLine;
        }

        $createdPrefix = '// Created: ';
        $createdLine = trim(fgets($handle));
        if(strpos($createdLine, $createdPrefix) !== 0) {
            echo '  Creation date is missing, queuing update...' . PHP_EOL;
            $headerLines['created'] = $createdPrefix . $now;
        }

        $updatedPrefix = '// Updated: ';
        $updatedLine = trim(fgets($handle));
        $updatedDate = substr($updatedLine, strlen($updatedPrefix));
        if(strpos($updatedLine, $updatedPrefix) !== 0 || (in_array($file, $changed) && $updatedDate !== $now)) {
            echo '  Updated date is inaccurate, queuing update...' . PHP_EOL;
            $headerLines['updated'] = $updatedPrefix . $now;
        }

        $blankLine = trim(fgets($handle));
        if(!empty($blankLine)) {
            echo '  Trailing newline missing, queuing update...' . PHP_EOL;
            $headerLines['blank'] = '';
        }

        if(!empty($headerLines)) {
            fclose($handle);

            try {
                $tmpName = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'ndx-uh-' . bin2hex(random_bytes(8)) . '.tmp';
                copy($file, $tmpName);

                $read = fopen($tmpName, 'rb');
                $handle = fopen($file, 'wb');

                fwrite($handle, fgets($read));

                $insertAfter = [];

                if(empty($headerLines['name']))
                    fwrite($handle, fgets($read));
                else {
                    $line = fgets($read);
                    if(strpos($line, '// ') !== 0)
                        $insertAfter[] = $line;

                    fwrite($handle, $headerLines['name'] . "\n");
                }

                if(empty($headerLines['created']))
                    fwrite($handle, fgets($read));
                else {
                    $line = fgets($read);
                    if(strpos($line, '// Created: ') !== 0)
                        $insertAfter[] = $line;

                    fwrite($handle, $headerLines['created'] . "\n");
                }

                if(empty($headerLines['updated']))
                    fwrite($handle, fgets($read));
                else {
                    $line = fgets($read);
                    if(strpos($line, '// Updated: ') !== 0)
                        $insertAfter[] = $line;

                    fwrite($handle, $headerLines['updated'] . "\n");
                }

                if(!isset($headerLines['blank']))
                    fwrite($handle, fgets($read));
                else {
                    $line = fgets($read);
                    if(!empty($line)) {
                        $insertAfter[] = $line;
                        fwrite($handle, "\n");
                    }
                }

                foreach($insertAfter as $line)
                    fwrite($handle, $line);

                while(($line = fgets($read)) !== false)
                    fwrite($handle, $line);
            } finally {
                if(is_resource($read))
                    fclose($read);

                if(is_file($tmpName))
                    unlink($tmpName);
            }
        }
    } finally {
        fclose($handle);
    }
}