<?php

/**
 * Class WpHttpRemoteGetRequest.
 *
 * @package AmpProject\AmpWP
 */
namespace Google\Web_Stories_Dependencies\AmpProject\AmpWP\RemoteRequest;

use Google\Web_Stories_Dependencies\AmpProject\Exception\FailedToGetFromRemoteUrl;
use Google\Web_Stories_Dependencies\AmpProject\RemoteGetRequest;
use Google\Web_Stories_Dependencies\AmpProject\RemoteRequest\RemoteGetRequestResponse;
use Google\Web_Stories_Dependencies\AmpProject\Response;
use Traversable;
use WP_Error;
use WP_Http;
/**
 * Remote request transport using the WordPress WP_Http abstraction layer.
 *
 * @package AmpProject\AmpWP
 * @since 2.0
 * @internal
 */
final class WpHttpRemoteGetRequest implements RemoteGetRequest
{
    /**
     * Default timeout value to use in seconds.
     *
     * @var int
     */
    const DEFAULT_TIMEOUT = 5;
    /**
     * Default number of retry attempts to do.
     *
     * @var int
     */
    const DEFAULT_RETRIES = 2;
    /**
     * List of HTTP status codes that are worth retrying for.
     *
     * @var int[]
     */
    const RETRYABLE_STATUS_CODES = [WP_Http::REQUEST_TIMEOUT, WP_Http::LOCKED, WP_Http::TOO_MANY_REQUESTS, WP_Http::INTERNAL_SERVER_ERROR, WP_Http::SERVICE_UNAVAILABLE, WP_Http::GATEWAY_TIMEOUT];
    /**
     * Whether to verify SSL certificates or not.
     *
     * @var boolean
     */
    private $ssl_verify;
    /**
     * Timeout value to use in seconds.
     *
     * @var int
     */
    private $timeout;
    /**
     * Number of retry attempts to do for an error that is worth retrying.
     *
     * @var int
     */
    private $retries;
    /**
     * Instantiate a WpHttpRemoteGetRequest object.
     *
     * @param bool $ssl_verify Optional. Whether to verify SSL certificates. Defaults to true.
     * @param int  $timeout    Optional. Timeout value to use in seconds. Defaults to 10.
     * @param int  $retries    Optional. Number of retry attempts to do if a status code was thrown that is worth
     *                         retrying. Defaults to 2.
     */
    public function __construct($ssl_verify = \true, $timeout = self::DEFAULT_TIMEOUT, $retries = self::DEFAULT_RETRIES)
    {
        if (!\is_int($timeout) || $timeout < 0) {
            $timeout = self::DEFAULT_TIMEOUT;
        }
        if (!\is_int($retries) || $retries < 0) {
            $retries = self::DEFAULT_RETRIES;
        }
        $this->ssl_verify = $ssl_verify;
        $this->timeout = $timeout;
        $this->retries = $retries;
    }
    /**
     * Do a GET request to retrieve the contents of a remote URL.
     *
     * @param string $url     URL to get.
     * @param array  $headers Optional. Associative array of headers to send with the request. Defaults to empty array.
     * @return Response Response for the executed request.
     * @throws FailedToGetFromRemoteUrl If retrieving the contents from the URL failed.
     */
    public function get($url, $headers = [])
    {
        $retries_left = $this->retries;
        do {
            $args = ['method' => 'GET', 'timeout' => $this->timeout, 'sslverify' => $this->ssl_verify, 'headers' => $headers];
            $response = \wp_remote_get($url, $args);
            if ($response instanceof WP_Error) {
                return new RemoteGetRequestResponse($response->get_error_message(), [], 500);
            }
            if (empty($response['response']['code'])) {
                return new RemoteGetRequestResponse(!empty($response['response']['message']) ? $response['response']['message'] : 'Unknown error', [], 500);
            }
            $status = $response['response']['code'];
            if ($status < 200 || $status >= 300) {
                if (!$retries_left || \in_array($status, self::RETRYABLE_STATUS_CODES, \true) === \false) {
                    throw FailedToGetFromRemoteUrl::withHttpStatus($url, $status);
                }
                continue;
            }
            $headers = $response['headers'];
            if ($headers instanceof Traversable) {
                $headers = \iterator_to_array($headers);
            }
            if (!\is_array($headers)) {
                $headers = [];
            }
            return new RemoteGetRequestResponse($response['body'], $headers, (int) $status);
        } while ($retries_left--);
        // This should never be triggered, but we want to ensure we always have a typed return value,
        // to make PHPStan happy.
        return new RemoteGetRequestResponse('', [], 500);
    }
}
