<?php

declare(strict_types=1);

namespace PhpWA\Transport;

use PhpWA\Exception\TransportException;
use PhpWA\Runtime\Deadline;

final class DirectStreamConnector implements StreamConnectorInterface
{
    public function connect(string $host, int $port, bool $secure, Deadline $deadline)
    {
        if (trim($host) === '' || $port < 1 || $port > 65535) {
            throw new TransportException('Invalid transport endpoint.');
        }
        $formatted = filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false ? '[' . $host . ']' : $host;
        $target = 'tcp://' . $formatted . ':' . $port;
        $errno = 0;
        $error = '';
        set_error_handler(static function (): bool { return true; });
        try {
            $stream = stream_socket_client(
                $target,
                $errno,
                $error,
                $deadline->remaining('TCP connection'),
                STREAM_CLIENT_CONNECT,
                stream_context_create()
            );
        } finally {
            restore_error_handler();
        }
        if (!is_resource($stream)) {
            throw new TransportException('Unable to establish TCP connection [' . $errno . '].');
        }
        try {
            stream_set_blocking($stream, true);
            if ($secure) { TlsStreamEnabler::enable($stream, $host, $deadline); }
            return $stream;
        } catch (\Throwable $exception) {
            fclose($stream);
            throw $exception;
        }
    }
}
