#import "AbstractConnection.h"
#import "FilePermissions.h"
#import "PCCredentials.h"

@class S3Parser;
@class S3RestRequest;

typedef enum S3ServiceType {
	kS3ServiceAmazonS3,
	kS3ServiceGoogleStorage
} S3Service;

@interface S3Connection : AbstractConnection
{
@private
	__weak NSString* iTransferFileName;
	__weak S3RestRequest* iRunningRequest;
	__weak id iStreamingHandler;
	
	S3Service iService;
	NSString* iServiceHost;
	NSString* iServiceHeaderPrefix;
	NSString* iServiceSignatureIdentifier;
	
	S3Parser* iParser;
	
	BOOL iUploading;
	unsigned long long iDownloadFileSize;
	
	NSString* iErrorServerMessage;
}

+ (BOOL)isDNSAbleBucketName:(NSString*)name;

+ (S3Service)serviceForCredentials:(PCCredentials*)credentials;
+ (NSString*)hostForService:(S3Service)service;

@end


@interface S3Connection (Regions)

+ (NSUInteger)numberOfRegions;
+ (NSString*)localizedNameForRegionIndex:(NSUInteger)rIndex;
+ (NSString*)locationConstraintForRegionIndex:(NSUInteger)rIndex;
+ (NSString*)bucketPrefixForRegionIndex:(NSUInteger)rIndex; // to be used when creating a new bucket

@end


@interface S3Connection (Authentication)

- (NSString*)authorizationForVerb:(NSString*)verb contentMD5:(NSString*)contentMD5 contentType:(NSString*)contentType timestamp:(NSString*)timestamp headers:(NSDictionary*)headers bucket:(NSString*)bucket path:(NSString*)path subResource:(NSString*)subResource;
- (NSString*)authorizationForCloudFrontTimestamp:(NSString*)timestamp;

@end


@interface S3Connection (Private)

- (S3RestRequest*)newRequestWithVerb:(NSString*)verb bucket:(NSString*)bucket path:(NSString*)path args:(NSString*)args;
- (S3RestRequest*)requestWithVerb:(NSString*)verb bucket:(NSString*)bucket path:(NSString*)path args:(NSString*)args;
- (BOOL)runRequest:(S3RestRequest*)request;

@end


@interface BucketLoggingStatus : NSObject
{
@private
	BOOL iEnabled;
	NSString* iTargetBucket;
	NSString* iTargetPrefix;
}

@property(getter=isEnabled) BOOL enabled;
@property(copy) NSString* targetBucket;
@property(copy) NSString* targetPrefix;

- (BOOL)isValid;

@end


// a distribution is inherently bucket-specific, so don't go running around trying to apply a distribution from one bucket to another since it will still affect the original bucket
@interface CloudFrontDistribution : NSObject
{
@private
	BOOL iPlaceholder;
	NSString* iReference;
	
	NSString* iIdentifier;
	NSString* iDomainName;
	NSString* iComment;
	NSArray* iCNAMEs;
	BOOL iEnabled;
}

@property(readonly, copy) NSString* reference;
@property(readonly, copy) NSString* identifier;
@property(readonly, copy) NSString* domainName;
@property(readonly, copy) NSString* comment;
@property(copy) NSArray* CNAMEs;
@property(getter=isEnabled) BOOL enabled;

// creates a special distribution to be used with kFTPKitAttributeCloudFrontDistributions attribute indicating that a new distribution should be created; reference can be used to locate it later
+ (CloudFrontDistribution*)distributionPlaceholder;

@end


@interface S3Connection (CloudFront)

- (NSArray*)distributionsForBucket:(NSString*)bucket error:(FTPKitError**)outError;
- (CloudFrontDistribution*)createDistributionForBucket:(NSString*)bucket reference:(NSString*)reference error:(FTPKitError**)outError;
- (BOOL)updateDistribution:(CloudFrontDistribution*)distribution error:(FTPKitError**)outError;
- (BOOL)deleteDistribution:(CloudFrontDistribution*)distribution error:(FTPKitError**)outError;

@end


enum {
	S3PermissionWorld = 0,
	S3PermissionAuthenticatedUsers = 1,
	S3PermissionOwner = 2,
	S3PermissionNone = 3
};


@interface FilePermissions (S3)

@property NSInteger S3ReadAccess;
@property NSInteger S3WriteAccess;

@end
