#import <stdint.h>

@class NSString;
@class NSURL;

// defines

#ifdef DEBUG
#define CACHE_DEBUG 0
#endif

// types

typedef uint32_t PCFileSystemType;
enum {
	PCFS_GenericItem = UINT32_C(0x464b6769), // 'FKgi'
	PCFS_File = UINT32_C(0x464b6669), // 'FKfi'
	PCFS_Folder = UINT32_C(0x464b666f), // 'FKfo'
	PCFS_Alias = UINT32_C(0x464b616c), // 'FKal'
	PCFS_SmartFolder = UINT32_C(0x464b736d) // 'FKsm'
};


typedef enum
{
	PCFS_SmallIcon = 16,
	PCFS_NormalIcon = 32,
	PCFS_ThumbnailIcon = 128,
	PCFS_512Icon = 512
} PCFileSystemIconSize;


typedef enum
{
	PCFS_OperationTypeInvalid = -1,
	PCFS_OperationTypeGeneric = 0,
	
	PCFS_LocalCopy = 1,
	PCFS_LocalListDirectory,
	PCFS_LocalMove,
	PCFS_LocalRename,
	PCFS_LocalNewFile,
	PCFS_LocalNewFolder,
	PCFS_LocalTrash,
	PCFS_LocalArchive,
	PCFS_LocalSumSize,
	PCFS_LocalChangeAttributes,
	PCFS_RemoteChangeDirectory,
	PCFS_RemoteListDirectory,
	PCFS_RemoteCacheNodes,
	PCFS_RemoteChangeAttributes,
	PCFS_RemoteConnect,
	PCFS_RemoteGetAttributes,
	PCFS_RemoteNewFile,
	PCFS_RemoteNewFolder,
	PCFS_RemoteTrash,
	PCFS_RemoteRename,
	PCFS_ResolveSymlink,
	PCFS_RemoteMove,
	PCFS_RemoteSumSize,
	PCFS_RemoteDownload,
	PCFS_RemoteUpload,
	PCFS_HTTPDownload,
	PCFS_RemotePublish,
	PCFS_RemoteCopy,
	PCFS_RawCommand,
	PCFS_RemoteReversePublish,
	PCFS_RemoteSynchronize,
	PCFS_RemoteFXP,
	
	PCFS_OperationTypeCount
} PCFileSystemOperationType;


typedef enum
{
	PCOperationStateReady = 0,
	PCOperationStateExecuting,
	PCOperationStateCancelled,
	PCOperationStateFinished
} PCOperationState;


// notifications

extern NSString* PCFSFolderContentsDidChangeNotification;
extern NSString* PCFSNodeAttributesChangedNotification;
extern NSString* PCFSDidDeleteNodesNotification;
extern NSString* PCFSFolderNeedsDisplayNotification;
extern NSString* PCFSDidOverwriteNodeNotification;
extern NSString* PCFSNodeNameChangedNotification;
extern NSString* PCFSNodeStatusDidChangeNotification; // optionally able to be delivered on worker thread

// constants

extern NSString* PCFSSortAscending;
extern NSString* PCFSSortDescending;
extern NSString* PCFSFileNode;
extern NSString* PCFSErrorNode;
extern NSString* PCFSErrorNodes;
extern NSString* PCFSConnection;
extern NSString* PCFSNotifyingOperation;
extern NSString* PCFSRemovedNodes;
extern NSString* PCFSDeletedNodes;
extern NSString* PCFSAddedNodes;
extern NSString* PCFSNodeStatus;

// Drag types for interapplication remote drag & drop

extern NSString* PCRemoteURLPboardType;

// user info keys for conflict resolution & other notifications

extern NSString* PCFSSourceNode;
extern NSString* PCFSDestinationNode;
extern NSString* PCFSCachedNode;

extern NSString* PCFSConflictBehavior;
extern NSString* PCFSName;
extern NSString* PCFSAlert;
extern NSString* PCFSAlertError; 	// NSError, the error generating the alert (may be nil)
extern NSString* PCFSAlertResponse; // NSNumber (NSInteger)
extern NSString* PCFSAlertUserInfo;


// transfer mode
enum {
	kFTPKitTransferModeAutomatic = -1
};


/* FTPKitProtocol
 * These are the types of server protocols that FTPKit supports.  Use these to 
 * create a connection with the proper subclass.
 */

typedef uint32_t FTPKitProtocol;
enum {
	kFTPKitProtocolFTP     = UINT32_C(0x46545020), // 'FTP ', "FTP"
	kFTPKitProtocolFTPSSL  = UINT32_C(0x4653534c), // 'FSSL', "FTP with Implicit SSL"
	kFTPKitProtocolFTPTLS  = UINT32_C(0x46545053), // 'FTPS', "FTP with TLS/SSL"
	kFTPKitProtocolSFTP    = UINT32_C(0x53465450), // 'SFTP', "SFTP"
	kFTPKitProtocolWebDAV  = UINT32_C(0x57444156), // 'WDAV', "WebDAV"
	kFTPKitProtocolWebDAVS = UINT32_C(0x53444156), // 'SDAV', "WebDAV with HTTPS"
	kFTPKitProtocolS3      = UINT32_C(0x53332020),  // 'S3  ', "Amazon S3"
	kFTPKitProtocolCloudFiles = UINT32_C(0x434c5544) // 'CLUD', "Rackspace Cloud Files"
};

extern FTPKitProtocol FTPKitProtocolFromURL(NSURL* URL);
extern NSString* FTPKitProtocolToScheme(FTPKitProtocol protocol);
extern uint32_t FTPKitProtocolToSecProtocol(FTPKitProtocol protocol);


/* FTPKitServerType
 * These types are used with the the server specific option 
 * "kFTPConnectionServerType".
 */

typedef int FTPKitServerType;
enum {
	// do not change existing values as they are saved in preferences
	kFTPKitServerTypeUnknown = 0,
	kFTPKitServerTypeUNIX = 1,
	kFTPKitServerTypePetersServer = 2,
	kFTPKitServerTypeWebStar = 3,
	kFTPKitServerTypeVMS = 4,
	kFTPKitServerTypeAppleShareIP = 5,
	kFTPKitServerTypeLukemftpd = 6,
	kFTPKitServerTypeWebStarUNIX = 7,
	kFTPKitServerTypeWindowsNT = 8,
	kFTPKitServerTypeWarFTPd = 9,
	kFTPKitServerTypeDiskXtender = 10,
	kFTPKitServerTypeFileZilla = 11,
	kFTPKitServerTypeBSD44 = 12,
	kFTPKitServerTypeSnapOS	= 13,
	kFTPKitServerTypeHummingBird = 14, // C:\\WINDOWS\\ paths
	kFTPKitServerGenericLastResort = 15,
	kFTPKitServerTypeTCPWareVMSUnix = 16,
	kFTPKitServerTypeNetware = 17,
	kFTPKitServerTypeConnectEnterprise = 18,
	kFTPKitServerTypeDriveHQ = 19,
	kFTPKitServerTypeGoogleUploads = 20,
	kFTPKitServerTypeDawningSNI = 21,
	kFTPKitServerTypeOS400 = 22,
	kFTPKitServerTypeYahooSmallBusiness = 23,
	kFTPKitServerTypeTViX = 24,
	kFTPKitServerTypePersonalFTPServerPro = 25,
	kFTPKitServerTypeKnownUnknown = 26,
	kFTPKitServerTypeMultiNetUnixEmulation = 27,
	kFTPKitServerTypeGenericSFTP = 100
};


/* FTPUNIXParserNameDateSpacing
 * These keys are for name date line spacing under
 * advanced prefs
 */

typedef int FTPUNIXParserNameDateSpacing;
enum {
	FTPUNIXParserNameDateSpacingUnknown = 0,
	FTPUNIXParserNameDateSpacingOne = 1,
	FTPUNIXParserNameDateSpacingTwo = 2,
	FTPUNIXParserNameDateSpacingOneOrTwo = 3
};


/* FTPSortType
 * These keys are for sorting folder contents
 */
 
typedef enum {
	kFTPSortTypeNone = 0,
	kFTPSortTypeDate,
	kFTPSortTypeDescendant,
	kFTPSortTypeDisplayName,
	kFTPSortTypeFolderAboveFile,
	kFTPSortTypeGroup,
	kFTPSortTypeKind,
	kFTPSortTypeOwner,
	kFTPSortTypePermissions,
	kFTPSortTypeSize
} FTPSortType;


#define DECLARE_KEY(key) extern NSString* const key
#define DECLARE_VALUE(value) extern NSString* const value

/* File Attributes
 * These attributes can be set on individual files via setAttributes:forItems:
 */

DECLARE_KEY(kFTPKitAttributeOwner); // NSString or NSNull if not applicable
DECLARE_KEY(kFTPKitAttributeGroup); // NSString or NSNull if not applicable
DECLARE_KEY(kFTPKitAttributeOwnerAccountID); // NSNumber
DECLARE_KEY(kFTPKitAttributeGroupAccountID); // NSNumber
DECLARE_KEY(kFTPKitAttributeS3CanonicalOwner); // NSString
DECLARE_KEY(kFTPKitAttributeBucketRegionIndex); // NSNumber
DECLARE_KEY(kFTPKitAttributeBucketLocationConstraint); // NSString
DECLARE_KEY(kFTPKitAttributeBucketLoggingStatus); // BucketLoggingStatus
DECLARE_KEY(kFTPKitAttributeCloudFrontDistributions); // NSArray of CloudFrontDistribution
DECLARE_KEY(kFTPKitAttributeContainerCDNEnabled); // NSNumber (BOOL)
DECLARE_KEY(kFTPKitAttributeContainerLogRetentionEnabled); // NSNumber (BOOL)
DECLARE_KEY(kFTPKitAttributeContainerCDNURI); // NSString

/* Custom file upload preference Keys */

DECLARE_KEY(kFTPKitPrefKeyDefaultFile); // NSDictionary - Also in TSPrefKeys
DECLARE_KEY(kFTPKitPrefKeyDefaultFolder); // NSDictionary - Also in TSPrefKeys
DECLARE_KEY(kFTPKitPrefKeyEnabled); // NSNumber (bool) - Also in TSPrefKeys
DECLARE_KEY(kFTPKitPrefKeyFTPPermissions); // NSNumber (octal) - Also in TSPrefKeys
DECLARE_KEY(kFTPKitPrefKeyS3Permissions); // NSNumber (octal) - Also in TSPrefKeys
DECLARE_KEY(kFTPKitPrefKeyWebDAVPermissions); // NSNumber (octal) - Also in TSPrefKeys

DECLARE_KEY(kFTPKitPrefKeyCustomS3UploadHeaders); // NSArray of NSDictionary with keys:
	DECLARE_KEY(kS3CustomUploadHeadersKeyExtension); // NSString, kS3CustomUploadHeadersValueDefaultExtension for default
	DECLARE_KEY(kS3CustomUploadHeadersKeyHeaders); // NSArray of NSDictionary with keys:
		DECLARE_KEY(kS3HeaderKeyEnabled); // NSNumber (bool)
		DECLARE_KEY(kS3HeaderKeyName); // NSString
		DECLARE_KEY(kS3HeaderKeyValue); // NSString

DECLARE_VALUE(kS3CustomUploadHeadersValueDefaultExtension);

/* custom file node property keys */

DECLARE_KEY(kCachedNode);

/* S3 and CloudFiles header keys */

DECLARE_KEY(kHTTPHeaderContentType);
DECLARE_KEY(kHTTPHeaderContentLength);
DECLARE_KEY(kHTTPHeaderDate);
DECLARE_KEY(kHTTPHeaderEtag);

// S3
DECLARE_KEY(kHTTPHeaderAuthorization);

// Cloud Files
DECLARE_KEY(kHTTPHeaderXAuthKey); 
DECLARE_KEY(kHTTPHeaderXAuthUser);
DECLARE_KEY(kHTTPHeaderXAuthToken);
DECLARE_KEY(kHTTPHeaderXCDNManagementURL);
DECLARE_KEY(kHTTPHeaderXStorageURL);
DECLARE_KEY(kHTTPHeaderOffset);
DECLARE_KEY(kHTTPHeaderXLogRetention);
DECLARE_KEY(kHTTPHeaderXCDNEnabled);
DECLARE_KEY(kHTTPHeaderLastModified);
DECLARE_KEY(kHTTPHeaderXCDNURI);

/* Notifications
 * Notifications not related to the File System
 */

DECLARE_KEY(kFTPKitNotificationCredentialOptionsDidChange);

/* NSError Domains
 * These are the domains which FTPKit will report errors on via the NSError API
 */

DECLARE_KEY(kFTPKitErrorDomain);

/* Exceptions
 */

DECLARE_KEY(kFTPKitParserFallback);

/*
 * Data is an id and error is NSError returned from operations
 */

DECLARE_KEY(kFTPKitOperationResult);
DECLARE_KEY(kFTPKitOperationContextInfo);
DECLARE_KEY(kFTPKitOperationError);

/*
 * Used as an NSError userInfo dictionary key with an NSString value for a server's response message.
 */

DECLARE_KEY(kFTPKitErrorKeyServerMessage);

#undef DECLARE_VALUE
#undef DECLARE_KEY


/* FTPKit Error Codes
 * These codes are used to define particular error states on callbacks.
 * 0 - 100 are used by the virtual file managers.
 * Note: When adding errors, make sure to add the conversion to the
 * abstraction connection subclasses' kitErrorForCode: class method.
 */

typedef enum {
	kFTPKitErrorNoError = 0,
	kFTPKitErrorCancelled = 1,
	kFTPKitErrorGeneric = 2,
	kFTPKitErrorUnknown = 3,
	kFTPKitErrorDisconnectBadAuth = 4,
	kFTPKitErrorDisconnectServerReset = 5,
	kFTPKitErrorConnectionRefused = 6,
	kFTPKitErrorCouldNotChangeDirectory = 7,
	kFTPKitErrorCouldNotListDirectory = 8,
	kFTPKitErrorPasswordRequired = 9,
	kFTPKitErrorFileAlreadyExists = 11,
	kFTPKitErrorCouldNotDelete = 12,
	kFTPKitErrorCouldNotCreate = 13,
	kFTPKitErrorFileNotFound = 14,
	kFTPKitErrorCouldNotAcquireConnection = 15,		/* error when the connection acquisition times out */
	kFTPKitErrorFXPFailure = 16,					/* error when specific FXP commands fail */
	kFTPKitErrorServerCommandNotSupported = 17,		/* error when not trying commands for specific servers */
	kFTPKitErrorPermissionDenied = 18,
	kFTPKitErrorConnectionError = 19,				/* generic error case for any sort of connection problems */
	kFTPKitErrorReadFailed = 20,
	kFTPKitErrorWriteFailed = 21,
	kFTPKitErrorHelperProcessFailed = 22,
	kFTPKitErrorMalformedResponse = 23,
	kFTPKitErrorSymlinkEncountered = 24,
	kFTPKitErrorAtomicSizeMismatch = 25,			/* error when the uploaded file isn't the same size as the source file */
	kFTPKitErrorCouldNotParseLine = 26,
	kFTPKitErrorCouldNotDetermineTimeOffset = 27,
	kFTPKitErrorCertificateVerificationFailed = 28,
	kFTPKitErrorCouldNotChangeAttributes = 29		/* error when connection can't set all requested attributes */
} FTPKitErrorCode;


/* NSConditionLock constants
*/

#define	kConditionIdle  0
#define kConditionBusy  1
#define kConditionDone  2

/* FTPKitConflictModes
 * These defines use the lower 8 bits of a UInt16 to represent the resume
 * mode for files.  The upper 8 bits are used to represent the resume mode for
 * folders.
 */

typedef uint16_t FTPKitConflictMode;
enum {
	kFTPKitConflictModeFileMask =             UINT16_C(0x00FF),
	kFTPKitConflictModeFileAsk =              UINT16_C(0x0001),
	kFTPKitConflictModeFileSkip =             UINT16_C(0x0002),
	kFTPKitConflictModeFileResume =           UINT16_C(0x0004),
	kFTPKitConflictModeFileOverwrite =        UINT16_C(0x0008),
	kFTPKitConflictModeFileCancel =           UINT16_C(0x0010),
	
	kFTPKitConflictModeFileDoForRemaining =   UINT16_C(0x0080), // 'OR' this value with an existing conflict type to get "apply to all" behavior
	
	kFTPKitConflictModeFolderMask =           UINT16_C(0xFF00),
	kFTPKitConflictModeFolderAsk =            UINT16_C(0x0100),
	kFTPKitConflictModeFolderSkip =           UINT16_C(0x0200),
	kFTPKitConflictModeFolderMerge =          UINT16_C(0x0400),
	kFTPKitConflictModeFolderOverwrite =      UINT16_C(0x0800),
	kFTPKitConflictModeFolderCancel =         UINT16_C(0x1000),
	
	kFTPKitConflictModeFolderDoForRemaining = UINT16_C(0x8000),  // 'OR' this value with an existing conflict type to get "apply to all" behavior
	
	kFTPKitConflictModeNone =                 UINT16_C(0x0000)
};

// The following macros are provided for convenience.  Feel free to bit
// twiddle FTPKitConflictMode's yourself.

// FTPKitConflictModeSetFolderMode(m, f)
// Sets the given folder mode on m (clears existing folder mode).
// m: A valid FTPKitConflictMode variable
// f: A folder conflict mode to set on m.
#define FTPKitConflictModeSetFolderMode(m, f) (m = (m & ~kFTPKitConflictModeFolderMask) | (f & kFTPKitConflictModeFolderMask))

// FTPKitConflictModeSetFileMode(m, f)
// Sets the given file mode on m (clears existing file mode).
// m: A valid FTPKitConflictMode variable
// f: A file conflict mode to set on m.
#define FTPKitConflictModeSetFileMode(m, f) (m = (m & ~kFTPKitConflictModeFileMask) | (f & kFTPKitConflictModeFileMask))

// FTPKitConflictModeIsSet(m, f)
// Returns true if the given mode is set on m.
// m: A valid FTPKitConflictMode variable
// f: A resume mode to check on m
#define FTPKitConflictModeIsSet(m, f) ((m & f) != 0)


// kFTPKitEncodingAutomatic indicates that the native connection encoding should be used or a reasonable default if none exists
#define kFTPKitEncodingAutomatic kCFStringEncodingInvalidId

// Default timeout when acquiring connections for use in operations
#define kFTPKitAcquireConnectionTimeout 600
