class S3Manager {

    @NonNull
    public Observable<String> upload(@NonNull final File file, @NonNull final String subDirectoryPath) {
        return s3ClientFactory.getAmazonS3()
                .flatMap(amazonS3 -> {
                    if (amazonS3.isPresent()) {
                        return s3KeyGeneratorFactory.get()
                                .flatMap(s3KeyGenerator -> Observable.fromCallable(() -> {
                                    final String key = subDirectoryPath + s3KeyGenerator.getS3Key() + file.getName();
                                    amazonS3.get().putObject(BUCKET, key, file);
                                    try {
                                        return amazonS3.get().getResourceUrl(BUCKET, key);
                                    } catch (Exception e) {
                                        throw new IOException("Caught Amazon S3 exception", e);
                                    }
                                }));
                    } else {
                        return Observable.error(new Exception("Failed to initialize the S3 client"));
                    }
                });
    }

    @Inject public  S3Manager(CognitoManager cognitoManager);
    @VisibleForTesting  S3Manager(@NonNull S3ClientFactory s3ClientFactory, @NonNull S3KeyGeneratorFactory s3KeyGeneratorFactory);

}