<?php

$data_time_start = microtime(true);

require_once 'vendor/autoload.php';

require_once 'post_adapter.php';
require_once 'fontawesome.php';

use Symfony\Component\Yaml\Yaml;

$SERVER_HOST = $_SERVER['HTTP_HOST'];
if(!preg_match('/^[\w\.]+$/', $SERVER_HOST)) {
    die();
}

$SERVER_PREFIX = "https://" . $SERVER_HOST;

$SITE_CONFIG = Yaml::parseFile('secrets/' . $SERVER_HOST . '.config.yml');
$SITE_CONFIG['uri_prefix'] = $SERVER_PREFIX;
$SITE_CONFIG['HTTP_HOST'] = $SERVER_HOST;

$adapter = new PostHandler($SITE_CONFIG);

$loader = new \Twig\Loader\FilesystemLoader(['./templates', './user_content']);

$twig = new \Twig\Environment($loader,['debug' => true]);
$twig->addExtension(new Twig\Extra\Markdown\MarkdownExtension());

use Twig\Extra\Markdown\DefaultMarkdown;
use Twig\Extra\Markdown\MarkdownRuntime;
use Twig\RuntimeLoader\RuntimeLoaderInterface;

function deduce_user_agent() {
    $real_agent=$_SERVER['HTTP_USER_AGENT'];

    if(preg_match('/(Googlebot|\w*Google\w*)/', $real_agent, $match)) {
        return "bot/google/" . $match[1];
    }
    elseif(preg_match('/(Mozilla|Chrome|Chromium)/', $real_agent, $match)) {
        return "user/" . $match[1];
    }
    else {
        return "unidentified";
    }
}

function log_and_die($path, $die_code = 0, $referrer = null) {
    global $data_time_start;
    global $adapter;

    $data_time_end = microtime(true);

    if(!isset($referrer)) {
        $referrer = 'magic';
        
        if(isset($_SERVER['HTTP_REFERER'])) {
            $referrer = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
        }
    }

    $adapter->log_post_access($path,
        deduce_user_agent(),
        $referrer,
        $data_time_end - $data_time_start);

    die($die_code);
}

$twig->addRuntimeLoader(new class implements RuntimeLoaderInterface {
    public function load($class) {
        if (MarkdownRuntime::class === $class) {
            return new MarkdownRuntime(new DefaultMarkdown());
        }
    }
});

function render_twig($template, $args = []) {
    global $twig;
    global $FONT_AWESOME_ARRAY;
    global $SITE_CONFIG;

    $args['fa'] = $FONT_AWESOME_ARRAY;
    
    $post = $args['post'] ?? [];
    $settings = $post['settings'] ?? [];
    $meta = $post['post_metadata'] ?? [];
    
    $args['banner'] ??= $settings['banners'] ?? $SITE_CONFIG['banners'];
    
    $args['og'] = array_merge([
        "site_name" => $SITE_CONFIG['opengraph']['site_name'],
        "title" => $meta['title'] ?? $SITE_CONFIG['opengraph']['site_name'],
        "url" => $_SERVER['REQUEST_URI'],
        "description" => $meta['description'] 
                        ?? $settings['description'] 
                        ?? $SITE_CONFIG['opengraph']['description']
    ], $args['og'] ?? []);
    
    if(($meta['type'] ?? '') == 'image') {
        $args['og']['image'] ??= $meta['media_file'];
    }

    $args['og']['image'] ??= $SITE_CONFIG['uri_prefix'] . $args['banner'][0]["src"];

    $args['banner'] = json_encode($args['banner']);

    $args['site_config'] = $SITE_CONFIG;

    echo $twig->render($template, $args);
}

function try_render_post($SURI) {
    global $adapter;

    $post = $adapter->get_post_by_path($SURI);

    if(!$post['found']) {
        echo render_twig('post_types/rrror.html',[
            "error_code" => '404 Hoard not found!',
            "error_description" => "Well, we searched 
                far and wide for `" . $SURI . "` but 
                somehow it must have gotten lost... Sorry!",
            "post" => array_merge($post, [
                "post_metadata" => ["title" => "404 ???"]
            ])
        ]);

        log_and_die('/404', referrer: ($_SERVER['HTTP_REFERER'] ?? 'magic'));
    }

    switch($post['post_metadata']['type']) {
    case 'directory':
        if(preg_match('/^(.*[^\/])((?:#.*)?)$/', $SURI, $match)) {
            header('Location: ' . $match[1] . '/' . $match[2]);
            
            die();
        }

        echo render_twig('post_types/directory.html', [ 
            "post" => $post,
            "subposts" => $adapter->get_subposts_by_path($SURI)
        ]);
    
    break;

    case 'text/markdown':
        echo render_twig('post_types/markdown.html', [ 
            "post" => $post
        ]);
    break;

    case 'image':
        echo render_twig('post_types/image.html', [
            "post" => $post,
        ]);
    break;
    }
}

function generate_website($SURI) {
    global $adapter;
    global $FONT_AWESOME_ARRAY;

    if(preg_match('/^\/api\/admin/', $SURI)) {
        header('Content-Type: application/json');

        $user_api_key = '';
        if(isset($_GET['api_key'])) {
            $user_api_key = $_GET['api_key'];
        }
        if(isset($_POST['api_key'])) {
            $user_api_key = $_POST['api_key'];
        }

        if($user_api_key != file_get_contents('secrets/api_admin_key')) {
            http_response_code(401);

            echo json_encode([
                "authorized" => false
            ]);

            log_and_die('/api/401');
        }

        if($SURI = '/api/admin/upload') {
            $adapter->handle_upload($_POST['post_path'], $_FILES['post_data']['tmp_name']);

            echo json_encode(["ok" => true]);
        }
    } elseif(preg_match('/^\/api/', $SURI)) {
        if($SURI == '/api/post_counters') {
            header('Content-Type: application/json');
            echo json_encode($adapter->get_post_access_counters());
        } elseif($SURI == '/api/metrics') {
            header('Content-Type: application/line');
            echo $adapter->get_post_access_counters_line();
        } elseif(preg_match('/^\/api\/posts(.*)$/', $SURI, $match)) {

            header('Content-Type: application/json');
            echo json_encode($adapter->get_post_by_path($match[1]));

        } elseif(preg_match('/^\/api\/subposts(.*)$/', $SURI, $match)) {

            header('Content-Type: application/json');
            echo json_encode(get_subposts($match[1]));
        } elseif($SURI == '/api/upload') {

            echo $twig->render('upload.html');
        }
    } elseif(preg_match('/^\/feed(?:\/(rss|atom)(.*))?$/', $SURI, $match)) {
        $feed = $adapter->get_laminas_feed($match[2] ?? '/', $match[1] ?? 'rss');

        header('Content-Type: application/xml');
        header('Cache-Control: max-age=1800');
        header('Etag: W/"' . $SURI . '/' . strtotime($feed['feed_ts']) . '"');

        echo $feed['feed'];
    } elseif(!preg_match('/^\s*text\/html/', $_SERVER['HTTP_ACCEPT'])) {
        header('Location: /raw' . $SURI);
        exit(0);
    } elseif(true) {
        try_render_post($SURI);
    }
}

$URL_PATH = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
generate_website($URL_PATH);

log_and_die($URL_PATH);

?>
