<?php
namespace Uiharu;

use Index\Data\IDbConnection;
use Index\Http\HttpFx;
use Syokuhou\IConfig;

final class UihContext {
    private IDbConnection $database;
    private IConfig $config;
    private HttpFx $router;
    private array $apis = [];
    private array $lookups = [];

    public function __construct(IDbConnection $database, IConfig $config) {
        $this->database = $database;
        $this->config = $config;
    }

    public function getDatabase(): IDbConnection {
        return $this->database;
    }

    public function getRouter(): HttpFx {
        return $this->router;
    }

    public function isOriginAllowed(string $origin): bool {
        $origin = mb_strtolower(parse_url($origin, PHP_URL_HOST));

        if($origin === $_SERVER['HTTP_HOST'])
            return true;

        $allowed = $this->config->getArray('cors:origins');
        if(empty($allowed))
            return true;

        return in_array($origin, $allowed);
    }

    public function setupHttp(): void {
        $this->router = new HttpFx;
        $this->router->use('/', function($response) {
            $response->setPoweredBy('Uiharu');
        });

        $this->router->use('/', function($response, $request) {
            $origin = $request->getHeaderLine('Origin');

            if(!empty($origin)) {
                if(!$this->isOriginAllowed($origin))
                    return 403;

                $response->setHeader('Access-Control-Allow-Origin', $origin);
                $response->setHeader('Vary', 'Origin');
            }
        });

        $this->router->use('/', function($response, $request) {
            if($request->getMethod() === 'OPTIONS') {
                $response->setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST');
                return 204;
            }
        });

        $this->router->get('/', function($response) {
            $response->accelRedirect('/index.html');
            $response->setContentType('text/html; charset=utf-8');
        });
    }

    public function dispatchHttp(...$args): void {
        $this->router->dispatch(...$args);
    }

    public function registerApi(IApi $api): void {
        $this->apis[] = $api;
    }

    public function matchApi(string $reqPath): void {
        $reqPath = '/' . trim(parse_url($reqPath, PHP_URL_PATH), '/');
        foreach($this->apis as $api)
            if($api->match($reqPath)) {
                $api->register($this->router);
                break;
            }
    }

    public function registerLookup(ILookup $lookup): void {
        $this->lookups[] = $lookup;
    }

    public function matchLookup(Url $url): ?ILookup {
        foreach($this->lookups as $lookup)
            if($lookup->match($url))
                return $lookup;
        return null;
    }
}