#!/usr/bin/php
<?php

array_shift($argv);

$opt = getopt('c::f:v', [ 'folder:', 'confirm', 'verbose', 'clean', 'old' ]);

if ( ! $opt ) {
    exit("Bad arguments provided, you must specify a fullpath using the -f or --folder option\n");
}

$iterator = new RecursiveIteratorIterator(new class(new RecursiveDirectoryIterator($opt['folder'] ?? $opt['f'], FilesystemIterator::SKIP_DOTS)) extends RecursiveFilterIterator {
    public function accept() : bool {
        return true;
    }
}, RecursiveIteratorIterator::SELF_FIRST);

$files = array();

foreach ($iterator as $info) {
    if ($info->getExtension() !== "php" || $info->isDir() ) {
        continue;
    }

    echo sprintf("\n### MIGRATING FILE %s\n", $info->getFilename());

    $opened = false;

    $attr = $newContent = [];

    $content = file_get_contents($info->getPathname());

    if ( isset($opt['clean']) ) {
        foreach (explode(PHP_EOL, $content) as $lineIdx => $line) {
            if ( $pos = strpos($line, '# migrated from: ') ) {
                $attr = true;

                $newContent[] = $newLine = substr($line, 0, $pos);

                echo sprintf("Changed line '%s' \n", trim($newLine));
            }
            else {
                $newContent[] = $line;
            }
        }

    }
    else {
        foreach (explode(PHP_EOL, $content) as $lineIdx => $line) {
            $tline = trim($line);

            if ($tline === "/**") {
                $opened = true;
            } elseif ($tline === '*/') {
                $opened = false;
            } elseif (substr($tline, 0, 1) === '*') {
                $annotation = trim(substr($tline, 1));

                if (strpos($annotation, '@') === 0) {
                    $argpos = strpos($annotation, '(');

                    if ($argpos !== false) {
                        $name = substr($annotation, 1, $argpos - 1);
                        $args = substr($annotation, $argpos + 1, strrpos($annotation, ')') - $argpos - 1);

                        try {
                            $array = eval("return [{$args}];");

                            $renderedArgs = [];

                            foreach ($array as $key => $argument) {

                                if (is_array($argument)) {
                                    $argument = var_export($argument, true);
                                } elseif (is_bool($argument)) {
                                    $argument = $argument ? 'true' : 'false';
                                } elseif (!is_numeric($argument)) {
                                    $argument = "\"$argument\"";
                                }

                                if (is_numeric($key)) {
                                    $renderedArgs[] = $argument;
                                } else {
                                    $renderedArgs[] = "$key: $argument";
                                }
                            }

                            $renderedArgs = implode(', ', $renderedArgs);
                        } catch (\Throwable $e) {
                            echo sprintf("!!! WARNING : %s in file (%s) line %d ; using previous notation.\n", $e->getMessage(), $info->getPathname(), $lineIdx + 1);

                            $renderedArgs = str_replace(' => ', ': ', $args);
                        }
                    } else {
                        $name = substr($annotation, 1);
                        $renderedArgs = "";
                    }

                    $attr[] = $attribute = sprintf("%s#[%s%s]%s", str_repeat(" ", strlen($line) - strlen(ltrim($line)) >= 4 ? 4 : 0), $name, $renderedArgs ? "($renderedArgs)" : "", $renderedArgs ? ( isset($opt['old']) ? " # migrated from: $args" : "" ) : "");

                    $newContent[] = $attribute;
                }
            } else {
                $newContent[] = $line;
            }
        }
    }

    $newContent = implode(PHP_EOL, $newContent);

    if ($attr) {
        if ( isset($opt['verbose']) || isset($opt['v']) ) {
            echo $newContent;
        }

        if ( isset($opt['confirm']) || isset($opt['c']) ) {
            file_put_contents($info->getPathname(), $newContent);

            echo sprintf("\n### FILE CONVERSION COMPLETED %s\n", $info->getFilename());
        }
        else {
            echo sprintf("\n### FILE CONVERSION ANALYZED, NOTHING WRITTEN UNTIL --confirm or -c FLAG IS PROVIDED %s\n", $info->getFilename());
        }
    }
    else {
        echo sprintf("\n### NOTHING TO DO ON FILE %s\n", $info->getFilename());
    }

}