<?php

namespace Aws\S3;

use Aws\AwsClientInterface;
use Aws\CommandInterface;
use Aws\ResultInterface;
use DateTime;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface;
use RuntimeException;

interface S3ClientInterface extends AwsClientInterface {
	/**
	 * Create a pre-signed URL for the given S3 command object.
	 *
	 * @param CommandInterface $command Command to create a pre-signed
	 *                                      URL for.
	 * @param int|string|DateTime $expires The time at which the URL should
	 *                                      expire. This can be a Unix
	 *                                      timestamp, a PHP DateTime object,
	 *                                      or a string that can be evaluated
	 *                                      by strtotime().
	 *
	 * @return RequestInterface
	 */
	public function createPresignedRequest( CommandInterface $command, $expires, array $options = [] );

	/**
	 * Returns the URL to an object identified by its bucket and key.
	 *
	 * The URL returned by this method is not signed nor does it ensure that the
	 * bucket and key given to the method exist. If you need a signed URL, then
	 * use the {@see \Aws\S3\S3Client::createPresignedRequest} method and get
	 * the URI of the signed request.
	 *
	 * @param string $bucket The name of the bucket where the object is located
	 * @param string $key The key of the object
	 *
	 * @return string The URL to the object
	 */
	public function getObjectUrl( $bucket, $key );

	/**
	 * Determines whether or not a bucket exists by name.
	 *
	 * @param string $bucket The name of the bucket
	 *
	 * @return bool
	 */
	public function doesBucketExist( $bucket );

	/**
	 * Determines whether or not an object exists by name.
	 *
	 * @param string $bucket The name of the bucket
	 * @param string $key The key of the object
	 * @param array $options Additional options available in the HeadObject
	 *                        operation (e.g., VersionId).
	 *
	 * @return bool
	 */
	public function doesObjectExist( $bucket, $key, array $options = [] );

	/**
	 * Register the Amazon S3 stream wrapper with this client instance.
	 */
	public function registerStreamWrapper();

	/**
	 * Deletes objects from Amazon S3 that match the result of a ListObjects
	 * operation. For example, this allows you to do things like delete all
	 * objects that match a specific key prefix.
	 *
	 * @param string $bucket Bucket that contains the object keys
	 * @param string $prefix Optionally delete only objects under this key prefix
	 * @param string $regex Delete only objects that match this regex
	 * @param array $options Aws\S3\BatchDelete options array.
	 *
	 * @throws RuntimeException if no prefix and no regex is given
	 * @see Aws\S3\S3Client::listObjects
	 */
	public function deleteMatchingObjects(
		$bucket,
		$prefix = '',
		$regex = '',
		array $options = []
	);

	/**
	 * Deletes objects from Amazon S3 that match the result of a ListObjects
	 * operation. For example, this allows you to do things like delete all
	 * objects that match a specific key prefix.
	 *
	 * @param string $bucket Bucket that contains the object keys
	 * @param string $prefix Optionally delete only objects under this key prefix
	 * @param string $regex Delete only objects that match this regex
	 * @param array $options Aws\S3\BatchDelete options array.
	 *
	 * @return PromiseInterface     A promise that is settled when matching
	 *                              objects are deleted.
	 * @see Aws\S3\S3Client::listObjects
	 *
	 */
	public function deleteMatchingObjectsAsync(
		$bucket,
		$prefix = '',
		$regex = '',
		array $options = []
	);

	/**
	 * Upload a file, stream, or string to a bucket.
	 *
	 * If the upload size exceeds the specified threshold, the upload will be
	 * performed using concurrent multipart uploads.
	 *
	 * The options array accepts the following options:
	 *
	 * - before_upload: (callable) Callback to invoke before any upload
	 *   operations during the upload process. The callback should have a
	 *   function signature like `function (Aws\Command $command) {...}`.
	 * - concurrency: (int, default=int(3)) Maximum number of concurrent
	 *   `UploadPart` operations allowed during a multipart upload.
	 * - mup_threshold: (int, default=int(16777216)) The size, in bytes, allowed
	 *   before the upload must be sent via a multipart upload. Default: 16 MB.
	 * - params: (array, default=array([])) Custom parameters to use with the
	 *   upload. For single uploads, they must correspond to those used for the
	 *   `PutObject` operation. For multipart uploads, they correspond to the
	 *   parameters of the `CreateMultipartUpload` operation.
	 * - part_size: (int) Part size to use when doing a multipart upload.
	 *
	 * @param string $bucket Bucket to upload the object.
	 * @param string $key Key of the object.
	 * @param mixed $body Object data to upload. Can be a
	 *                        StreamInterface, PHP stream resource, or a
	 *                        string of data to upload.
	 * @param string $acl ACL to apply to the object (default: private).
	 * @param array $options Options used to configure the upload process.
	 *
	 * @return ResultInterface Returns the result of the upload.
	 * @see Aws\S3\MultipartUploader for more info about multipart uploads.
	 */
	public function upload(
		$bucket,
		$key,
		$body,
		$acl = 'private',
		array $options = []
	);

	/**
	 * Upload a file, stream, or string to a bucket asynchronously.
	 *
	 * @param string $bucket Bucket to upload the object.
	 * @param string $key Key of the object.
	 * @param mixed $body Object data to upload. Can be a
	 *                        StreamInterface, PHP stream resource, or a
	 *                        string of data to upload.
	 * @param string $acl ACL to apply to the object (default: private).
	 * @param array $options Options used to configure the upload process.
	 *
	 * @return PromiseInterface     Returns a promise that will be fulfilled
	 *                              with the result of the upload.
	 * @see self::upload
	 */
	public function uploadAsync(
		$bucket,
		$key,
		$body,
		$acl = 'private',
		array $options = []
	);

	/**
	 * Copy an object of any size to a different location.
	 *
	 * If the upload size exceeds the maximum allowable size for direct S3
	 * copying, a multipart copy will be used.
	 *
	 * The options array accepts the following options:
	 *
	 * - before_upload: (callable) Callback to invoke before any upload
	 *   operations during the upload process. The callback should have a
	 *   function signature like `function (Aws\Command $command) {...}`.
	 * - concurrency: (int, default=int(5)) Maximum number of concurrent
	 *   `UploadPart` operations allowed during a multipart upload.
	 * - params: (array, default=array([])) Custom parameters to use with the
	 *   upload. For single uploads, they must correspond to those used for the
	 *   `CopyObject` operation. For multipart uploads, they correspond to the
	 *   parameters of the `CreateMultipartUpload` operation.
	 * - part_size: (int) Part size to use when doing a multipart upload.
	 *
	 * @param string $fromBucket Bucket where the copy source resides.
	 * @param string $fromKey Key of the copy source.
	 * @param string $destBucket Bucket to which to copy the object.
	 * @param string $destKey Key to which to copy the object.
	 * @param string $acl ACL to apply to the copy (default: private).
	 * @param array $options Options used to configure the upload process.
	 *
	 * @return ResultInterface Returns the result of the copy.
	 * @see Aws\S3\MultipartCopy for more info about multipart uploads.
	 */
	public function copy(
		$fromBucket,
		$fromKey,
		$destBucket,
		$destKey,
		$acl = 'private',
		array $options = []
	);

	/**
	 * Copy an object of any size to a different location asynchronously.
	 *
	 * @param string $fromBucket Bucket where the copy source resides.
	 * @param string $fromKey Key of the copy source.
	 * @param string $destBucket Bucket to which to copy the object.
	 * @param string $destKey Key to which to copy the object.
	 * @param string $acl ACL to apply to the copy (default: private).
	 * @param array $options Options used to configure the upload process.
	 *
	 * @return PromiseInterface     Returns a promise that will be fulfilled
	 *                              with the result of the copy.
	 * @see self::copy for more info about the parameters above.
	 */
	public function copyAsync(
		$fromBucket,
		$fromKey,
		$destBucket,
		$destKey,
		$acl = 'private',
		array $options = []
	);

	/**
	 * Recursively uploads all files in a given directory to a given bucket.
	 *
	 * @param string $directory Full path to a directory to upload
	 * @param string $bucket Name of the bucket
	 * @param string $keyPrefix Virtual directory key prefix to add to each upload
	 * @param array $options Options available in Aws\S3\Transfer::__construct
	 *
	 * @see Aws\S3\Transfer for more options and customization
	 */
	public function uploadDirectory(
		$directory,
		$bucket,
		$keyPrefix = null,
		array $options = []
	);

	/**
	 * Recursively uploads all files in a given directory to a given bucket.
	 *
	 * @param string $directory Full path to a directory to upload
	 * @param string $bucket Name of the bucket
	 * @param string $keyPrefix Virtual directory key prefix to add to each upload
	 * @param array $options Options available in Aws\S3\Transfer::__construct
	 *
	 * @return PromiseInterface A promise that is settled when the upload is
	 *                          complete.
	 * @see Aws\S3\Transfer for more options and customization
	 *
	 */
	public function uploadDirectoryAsync(
		$directory,
		$bucket,
		$keyPrefix = null,
		array $options = []
	);

	/**
	 * Downloads a bucket to the local filesystem
	 *
	 * @param string $directory Directory to download to
	 * @param string $bucket Bucket to download from
	 * @param string $keyPrefix Only download objects that use this key prefix
	 * @param array $options Options available in Aws\S3\Transfer::__construct
	 */
	public function downloadBucket(
		$directory,
		$bucket,
		$keyPrefix = '',
		array $options = []
	);

	/**
	 * Downloads a bucket to the local filesystem
	 *
	 * @param string $directory Directory to download to
	 * @param string $bucket Bucket to download from
	 * @param string $keyPrefix Only download objects that use this key prefix
	 * @param array $options Options available in Aws\S3\Transfer::__construct
	 *
	 * @return PromiseInterface A promise that is settled when the download is
	 *                          complete.
	 */
	public function downloadBucketAsync(
		$directory,
		$bucket,
		$keyPrefix = '',
		array $options = []
	);

	/**
	 * Returns the region in which a given bucket is located.
	 *
	 * @param string $bucketName
	 *
	 * @return string
	 */
	public function determineBucketRegion( $bucketName );

	/**
	 * Returns a promise fulfilled with the region in which a given bucket is
	 * located.
	 *
	 * @param string $bucketName
	 *
	 * @return PromiseInterface
	 */
	public function determineBucketRegionAsync( $bucketName );
}
