<?php
namespace Misuzu\Info;

use Index\Routing\IRouter;
use Misuzu\Template;
use Misuzu\Parsers\Parser;

class InfoRoutes {
    private const DOCS_PATH = MSZ_ROOT . '/docs';
    private const PROJECT_PATHS = [
        'misuzu' => MSZ_ROOT,
        'index' => MSZ_ROOT . '/vendor/flashwave/index',
    ];
    private const PROJECT_SUFFIXES = [
        'misuzu' => 'Misuzu Project » %s',
        'index' => 'Index Project » %s',
    ];

    public function __construct(IRouter $router) {
        $router->get('/info', [$this, 'getIndex']);
        $router->get('/info/:name', [$this, 'getDocsPage']);
        $router->get('/info/:project/:name', [$this, 'getProjectPage']);

        $router->get('/info.php', function($response) {
            $response->redirect(url('info'), true);
        });
        $router->get('/info.php/:name', function($response, $request, string $name) {
            $response->redirect(url('info', ['title' => $name]), true);
        });
        $router->get('/info.php/:project/:name', function($response, $request, string $project, string $name) {
            $response->redirect(url('info', ['title' => $project . '/' . $name]), true);
        });
    }

    private static function checkName(string $name): bool {
        return preg_match('#^([A-Za-z0-9_]+)$#', $name) === 1;
    }

    public function getIndex() {
        return Template::renderRaw('info.index');
    }

    public function getDocsPage($response, $request, string $name) {
        if(!self::checkName($name))
            return 404;

        return $this->serveMarkdownDocument(
            sprintf('%s/%s.md', self::DOCS_PATH, $name)
        );
    }

    public function getProjectPage($response, $request, string $project, string $name) {
        if(!array_key_exists($project, self::PROJECT_PATHS))
            return 404;
        if(!self::checkName($name))
            return 404;

        $projectPath = self::PROJECT_PATHS[$project];
        $titleSuffix = array_key_exists($project, self::PROJECT_SUFFIXES) ? self::PROJECT_SUFFIXES[$project] : '';

        $attempts = 0;
        $licenceHack = false;
        for(;;) {
            $path = match(++$attempts) {
                1 => sprintf('%s/%s', $projectPath, $name),
                2 => sprintf('%s/%s.md', $projectPath, $name),
                3 => sprintf('%s/%s', $projectPath, strtoupper($name)),
                4 => sprintf('%s/%s.md', $projectPath, strtoupper($name)),
                5 => sprintf('%s/%s', $projectPath, strtolower($name)),
                6 => sprintf('%s/%s.md', $projectPath, strtolower($name)),
                default => '',
            };

            if($path === '') {
                if(!$licenceHack) {
                    $isBritish = strtolower($name) === 'licence';
                    $isAmerican = strtolower($name) === 'license';

                    if($isBritish || $isAmerican) {
                        $attempts = 0;
                        $licenceHack = true;
                        $name = $isAmerican ? 'licence' : 'license';
                        continue;
                    }
                }

                return 404;
            }

            if(is_file($path))
                break;
        }

        return $this->serveMarkdownDocument($path, $titleSuffix);
    }

    private function serveMarkdownDocument(string $path, string $titleFormat = '') {
        if(!is_file($path))
            return 404;

        $body = file_get_contents($path);

        if(str_starts_with($body, '#')) {
            $offset = strpos($body, "\n");
            $title = trim(substr($body, 1, $offset));
            $body = substr($body, $offset);
        } else
            $title = ucfirst(basename($path));

        if($titleFormat !== '')
            $title = sprintf($titleFormat, $title);

        $body = Parser::instance(Parser::MARKDOWN)->parseText($body);

        return Template::renderRaw('info.view', [
            'document' => [
                'title' => $title,
                'content' => $body,
            ],
        ]);
    }
}
