<?php

namespace Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Future;

use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
use Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException;
use Google\Site_Kit_Dependencies\React\Promise\PromiseInterface;
/**
 * Implements common future functionality built on top of promises.
 */
trait BaseFutureTrait
{
    /** @var callable */
    private $waitfn;
    /** @var callable */
    private $cancelfn;
    /** @var PromiseInterface */
    private $wrappedPromise;
    /** @var \Exception Error encountered. */
    private $error;
    /** @var mixed Result of the future */
    private $result;
    private $isRealized = \false;
    /**
     * @param PromiseInterface $promise Promise to shadow with the future.
     * @param callable         $wait    Function that blocks until the deferred
     *                                  computation has been resolved. This
     *                                  function MUST resolve the deferred value
     *                                  associated with the supplied promise.
     * @param callable         $cancel  If possible and reasonable, provide a
     *                                  function that can be used to cancel the
     *                                  future from completing.
     */
    public function __construct(\Google\Site_Kit_Dependencies\React\Promise\PromiseInterface $promise, callable $wait = null, callable $cancel = null)
    {
        $this->wrappedPromise = $promise;
        $this->waitfn = $wait;
        $this->cancelfn = $cancel;
    }
    public function wait()
    {
        if (!$this->isRealized) {
            $this->addShadow();
            if (!$this->isRealized && $this->waitfn) {
                $this->invokeWait();
            }
            if (!$this->isRealized) {
                $this->error = new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\RingException('Waiting did not resolve future');
            }
        }
        if ($this->error) {
            throw $this->error;
        }
        return $this->result;
    }
    public function promise()
    {
        return $this->wrappedPromise;
    }
    public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
    {
        return $this->wrappedPromise->then($onFulfilled, $onRejected, $onProgress);
    }
    public function cancel()
    {
        if (!$this->isRealized) {
            $cancelfn = $this->cancelfn;
            $this->waitfn = $this->cancelfn = null;
            $this->isRealized = \true;
            $this->error = new \Google\Site_Kit_Dependencies\GuzzleHttp\Ring\Exception\CancelledFutureAccessException();
            if ($cancelfn) {
                $cancelfn($this);
            }
        }
    }
    private function addShadow()
    {
        // Get the result and error when the promise is resolved. Note that
        // calling this function might trigger the resolution immediately.
        $this->wrappedPromise->then(function ($value) {
            $this->isRealized = \true;
            $this->result = $value;
            $this->waitfn = $this->cancelfn = null;
        }, function ($error) {
            $this->isRealized = \true;
            $this->error = $error;
            $this->waitfn = $this->cancelfn = null;
        });
    }
    private function invokeWait()
    {
        try {
            $wait = $this->waitfn;
            $this->waitfn = null;
            $wait();
        } catch (\Exception $e) {
            // Defer can throw to reject.
            $this->error = $e;
            $this->isRealized = \true;
        }
    }
}
