<?php
namespace Misuzu\Info;

use Index\Routing\Route;
use Index\Routing\RouteHandler;
use Misuzu\Template;
use Misuzu\Parsers\Parser;
use Misuzu\URLs\URLInfo;

class InfoRoutes extends RouteHandler {
    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',
    ];

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

    #[Route('GET', '/info')]
    #[URLInfo('info-index', '/info')]
    public function getIndex() {
        return Template::renderRaw('info.index');
    }

    #[Route('GET', '/info/:name')]
    #[URLInfo('info', '/info/<title>')]
    #[URLInfo('info-doc', '/info/<title>')]
    public function getDocsPage($response, $request, string $name) {
        if(!self::checkName($name))
            return 404;

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

    private static function findDocPath(string $projectPath, string $name): string {
        // User provided case, without extension
        $attempt = sprintf('%s/%s', $projectPath, $name);
        if(is_file($attempt))
            return $attempt;

        // User provided case, with extension
        $attempt = sprintf('%s/%s.md', $projectPath, $name);
        if(is_file($attempt))
            return $attempt;

        $name = strtoupper($name);

        // Uppercase, without extension
        $attempt = sprintf('%s/%s', $projectPath, $name);
        if(is_file($attempt))
            return $attempt;

        // Uppercase, with extension
        $attempt = sprintf('%s/%s.md', $projectPath, $name);
        if(is_file($attempt))
            return $attempt;

        $name = strtolower($name);

        // Lowercase, without extension
        $attempt = sprintf('%s/%s', $projectPath, $name);
        if(is_file($attempt))
            return $attempt;

        // Lowercase, with extension
        $attempt = sprintf('%s/%s.md', $projectPath, $name);
        if(is_file($attempt))
            return $attempt;

        return '';
    }

    #[Route('GET', '/info/:project/:name')]
    #[URLInfo('info-project-doc', '/info/<project>/<title>')]
    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] : '';

        $path = self::findDocPath($projectPath, $name);
        if($path === '') {
            $isBritishLicense = strtolower($name) === 'licence';
            $isAmericanLicence = strtolower($name) === 'license';

            if($isBritishLicense || $isAmericanLicence) {
                $name = $isAmericanLicence ? 'licence' : 'license';
                $path = self::findDocPath($projectPath, $name);

                if($path === '')
                    return 404;
            } else
                return 404;
        }

        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,
            ],
        ]);
    }
}
