<?php declare(strict_types=1);

namespace GraphQL\Executor\Promise;

/**
 * Provides a means for integration of async PHP platforms ([related docs](data-fetching.md#async-php)).
 *
 * @template TAdopted = mixed
 */
interface PromiseAdapter
{
    /**
     * Is the value a promise or a deferred of the underlying platform?
     *
     * @param mixed $value
     *
     * @api
     */
    public function isThenable($value): bool;

    /**
     * Converts thenable of the underlying platform into GraphQL\Executor\Promise\Promise instance.
     *
     * @param mixed $thenable
     *
     * @phpstan-return Promise<TAdopted>
     *
     * @api
     */
    public function convertThenable($thenable): Promise;

    /**
     * Accepts our Promise wrapper, extracts adopted promise out of it and executes actual `then` logic described
     * in Promises/A+ specs. Then returns new wrapped instance of GraphQL\Executor\Promise\Promise.
     *
     * @phpstan-param Promise<covariant TAdopted> $promise
     *
     * @phpstan-return Promise<TAdopted>
     *
     * @api
     */
    public function then(Promise $promise, ?callable $onFulfilled = null, ?callable $onRejected = null): Promise;

    /**
     * Creates a Promise from the given resolver callable.
     *
     * @param callable(callable $resolve, callable $reject): void $resolver
     *
     * @phpstan-return Promise<TAdopted>
     *
     * @api
     */
    public function create(callable $resolver): Promise;

    /**
     * Creates a fulfilled Promise for a value if the value is not a promise.
     *
     * @param mixed $value
     *
     * @phpstan-return Promise<TAdopted>
     *
     * @api
     */
    public function createFulfilled($value = null): Promise;

    /**
     * Return a promise rejected with the given reason.
     *
     * @phpstan-return Promise<TAdopted>
     *
     * @api
     */
    public function createRejected(\Throwable $reason): Promise;

    /**
     * Given an iterable of promises (or values), returns a promise that is fulfilled when all the
     * items in the iterable are fulfilled.
     *
     * @param iterable<Promise|mixed> $promisesOrValues
     *
     * @phpstan-return Promise<TAdopted>
     *
     * @api
     */
    public function all(iterable $promisesOrValues): Promise;
}
