#!/usr/bin/env php
<?php

namespace BenTools\MercurePHP;

require __DIR__.'/../vendor/autoload.php';

use BenTools\MercurePHP\Configuration\Configuration;
use BenTools\MercurePHP\Hub\HubFactory;
use Psr\Log\LogLevel;
use React\EventLoop\Factory;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Logger\ConsoleLogger;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\SingleCommandApplication;
use Symfony\Component\Console\Style\SymfonyStyle;

$app = new SingleCommandApplication();
$app->setCode(
    function (InputInterface $input, OutputInterface $output): int {
        $output = new SymfonyStyle($input, $output);
        $logger = new ConsoleLogger($output, [LogLevel::INFO => OutputInterface::VERBOSITY_NORMAL]);
        try {
            $config = (new Configuration())
                ->overrideWith($_SERVER)
                ->overrideWith(
                    \array_filter(
                        $input->getOptions(),
                        fn ($value) => null !== nullify($value) && false !== $value
                    )
                )
                ->asArray();

            $loop = Factory::create();
            $hub = (new HubFactory($config, $logger))->create($loop);
            $hub->run($loop);

            return 0;
        } catch (\Exception $e) {
            $output->error($e->getMessage());

            return 1;
        }
    }
);

$app
    ->addOption(
        'addr',
        null,
        InputOption::VALUE_OPTIONAL,
        'The address to listen on.',
    )
    ->addOption(
        'transport-url',
        null,
        InputOption::VALUE_OPTIONAL,
        'The DSN to transport messages.',
    )
    ->addOption(
        'storage-url',
        null,
        InputOption::VALUE_OPTIONAL,
        'The DSN to store messages.',
    )
    ->addOption(
        'metrics-url',
        null,
        InputOption::VALUE_OPTIONAL,
        'The DSN to store metrics.',
    )
    ->addOption(
        'cors-allowed-origins',
        null,
        InputOption::VALUE_OPTIONAL,
        'A list of allowed CORS origins, can be * for all.',
    )
    ->addOption(
        'jwt-key',
        null,
        InputOption::VALUE_OPTIONAL,
        'The JWT key to use for both publishers and subscribers',
    )
    ->addOption(
        'jwt-algorithm',
        null,
        InputOption::VALUE_OPTIONAL,
        'The JWT verification algorithm to use for both publishers and subscribers, e.g. HS256 (default) or RS512.',
    )
    ->addOption(
        'publisher-jwt-key',
        null,
        InputOption::VALUE_OPTIONAL,
        'Must contain the secret key to valid publishers\' JWT, can be omitted if jwt_key is set.',
    )
    ->addOption(
        'publisher-jwt-algorithm',
        null,
        InputOption::VALUE_OPTIONAL,
        'The JWT verification algorithm to use for publishers, e.g. HS256 (default) or RS512.',
    )
    ->addOption(
        'subscriber-jwt-key',
        null,
        InputOption::VALUE_OPTIONAL,
        'Must contain the secret key to valid subscribers\' JWT, can be omitted if jwt_key is set.',
    )
    ->addOption(
        'subscriber-jwt-algorithm',
        null,
        InputOption::VALUE_OPTIONAL,
        'The JWT verification algorithm to use for subscribers, e.g. HS256 (default) or RS512.',
    )
    ->addOption(
        'allow-anonymous',
        null,
        InputOption::VALUE_NONE,
        'Allows subscribers with no valid JWT to connect.',
    );

$app->run();
