<?php

/*
 * This file is part of the ActivityPhp package.
 *
 * Copyright (c) landrok at github.com/landrok
 *
 * For the full copyright and license information, please see
 * <https://github.com/landrok/activitypub/blob/master/LICENSE>.
 */

namespace ActivityPhp\Server\Http;

use ActivityPhp\Server;
use ActivityPhp\Type\Util;
use Exception;

/**
 * A simple WebFinger discoverer tool
 */ 
class WebFingerFactory
{
    const WEBFINGER_URL = '%s://%s%s/.well-known/webfinger?resource=acct:%s';

    /**
     * @var null|\ActivityPhp\Server
     */
    protected static $server;

    /**
     * @var array An array of key => value. 
     * Keys are handle, values are WebFinger instances.
     */
    protected static $webfingers = [];

    /**
     * Get a profile via WebFinger protocol
     * 
     * @param string $handle
     * @param string $scheme Only for testing purpose
     * @return \ActivityPhp\Server\Http\WebFinger
     * @throws \Exception if handle is malformed.
     */
    public static function get(string $handle, string $scheme = 'https')
    {
        if (!preg_match(
                '/^@?(?P<user>[\w\-\.]+)@(?P<host>[\w\.\-]+)(?P<port>:[\d]+)?$/',
                $handle,
                $matches
            )
        ) {
            throw new Exception(
                "WebFinger handle is malformed '{$handle}'"
            );
        }

        // Unformat Mastodon handle @user@host => user@host
        $handle = strpos($handle, '@') === 0
            ? substr($handle, 1) : $handle;

        // Build a WebFinger URL
        $url = sprintf(
            self::WEBFINGER_URL,
            $scheme,
            $matches['host'],
            isset($matches['port']) ? $matches['port'] : '',
            $handle
        );

        $content = Util::decodeJson(
            (new Request(
                self::$server->config('http.timeout'),
                self::$server->config('http.agent')
            ))->get($url)
        );

        if (!is_array($content) || !count($content)) {
            throw new Exception('WebFinger fetching has failed');
        }

        self::$webfingers[$handle] = new WebFinger($content);

        return self::$webfingers[$handle];
    }

    /**
     * Inject a server instance
     * 
     * @param  \ActivityPhp\Server $server
     */
    public static function setServer(Server $server)
    {
        self::$server = $server;
    }
}
