//
//  MCClientServerDefines.h
//  MCClientServer
//
//  Created by Brent Gulanowski on 10-02-19.
//  Copyright 2010 Marketcircle Inc. All rights reserved.
//


#import <MCServerSupport/MCEventTracking.h>

#import <Foundation/Foundation.h>


#import "MCSSharedConstants.h"



// Protocol Messages
#define MCS_AUTHORIZATION_VERSION 4
#define MCS_DATABASE_LIST_VERSION 2


// This is defined in MCNetComm
extern NSString *kMCNCCommandKey;

extern NSString* kHostedAccessdServer;
extern NSString* kHostedTouchServer;

// Offline Record Keys
extern NSString* kMCServerReplicaNameKey;
extern NSString* kMCServerReplicaLastSyncDateKey;
extern NSString* kMCServerReplicaUserNameKey;
extern NSString* kMCServerReplicaIdentifierKey;
extern NSString* kMCServerReplicaOffsetIDKey;
extern NSString* kMCServerReplicaOfflineIDKey;
extern NSString* kMCServerReplicaStatusCodeKey;
extern NSString* kMCServerReplicaStatusStringKey;

extern NSString* kMCAServiceAddressKey;
extern NSString* kMCAServicePortKey;

//// Daemon Keeper Constants

// Daemon Keeper Error Domaain
extern NSString *kMCSDaemonKeeperDomain;

// Error Codes
typedef enum {
	kMCSDaemonErrorUndefined,
	kMCSDaemonErrorServerStartup,
	kMCSDaemonErrorServerShutdown,
	kMCSDaemonErrorDatabaseShutdown,
	kMCSDaemonErrorDaemonUnload,
	kMCSDaemonErrorDaemonLoad,
	
} MCSDaemonKeeperErrorCode;


// Authentication Error Domain
extern NSString* kMCSAuthenticationDomain;


// Authentication Error Codes
typedef enum {
	
	MCSAuthenticationNoError = 0,
	MCSAuthenticationUnknownError = 1,
	
	MCSAuthenticationServerUnavailableError = 100,
	MCSAuthenticationDatabaseServerUnavailableError = 101,
	
	MCSAuthenticationNoDatabaseError = 200,
	MCSAuthenticationIncorrectLoginError = 201,
	MCSAuthenticationExceedLicenses = 202,
	MCSAuthenticationServerSchemaNewerError = 203,
	MCSAuthenticationServerSchemaOlderError = 204,
	MCSAuthenticationServerVersionNewerError = 205,
	MCSAuthenticationServerVersionOlderError = 206,
	
	MCSAuthenticationServerReplicaResetError = 207,
	MCSAuthenticationServerReplicaWipeError = 208,
	
	MCSAuthenticationLicenseExpired = 209,
	MCSAuthenticationTrialExpired = 210,
	MCSAuthenticationReplicaRestricted = 211,
	MCSAuthenticationDatabaseMismatch = 212,
	MCSAuthenticationProcessHung = 213, // sync helper is hung
    MCSAuthenticationServiceTemporarilyUnavailable = 214, // service is down for maintenance. PG and other processes will not be hit. Accessd, touchd etc... simply return this and die.
    MCSAuthenticationAccountTemporarilyUnavailable = 215, // account could be moving to another server. In this case the service could be fine for other users and we hit the backend services as normal.
    MCSAuthenticationAccountRequiresUserAction = 216, // some users don't respond to email, so we fail sync and ask them to contact us asap.
    MCSAuthenticationDeviceReplicaLocked = 217, // The stage for this particular device is in some weird state. Your other devices could be syncing fine. Support will probably have to intervene.
	
} MCSAuthenticationErrorCode;


// DatabaseList Error Domain
extern NSString* kMCSDatabaseListDomain;

// Database List Error Codes
typedef enum {
	
	kMCSDatabaseListUnknownError = 1,
    
    kMCSDatabaseListServerUnavailableError = 100,
    kMCSDatabaseListVersionIncompatible = 101
	
} MCSDatabaseListErrorCode;


//// Replication Constants
// Database Types
typedef enum {
	kMCSDatabaseTypeStandard = 0,
	kMCSDatabaseTypeSample = 1,
	kMCSDatabaseTypeOffline = 2,
    kMCSDatabaseTypeMirror = 3,
	kMCSDatabaseTypeHosted = 4
} MCSDatabaseType;


// Database Replicant Types
typedef enum {
	kMCSReplicaTypeUndefined = 0,
	kMCSReplicaTypeOffline = 1,
	kMCSReplicaTypeTouch = 2,
	kMCSReplicaTypeMirror =3
} MCSReplicaType;

typedef enum {
	kMCSReplicaStatusUndefined = -1,
	kMCSReplicaStatusActive = 0,
	kMCSReplicaStatusRetired = 1,
	kMCSReplicaStatusSyncFailed = 2,
	kMCSReplicaStatusSyncOverdue = 3,
	kMCSReplicaStatusWaitingToWipe = 4,
	kMCSReplicaStatusInitInProgress = 5,
	kMCSReplicaStatusOnline =6,
	kMCSReplicaStatusRevoked = 7
} MCSReplicaStatus;

// Used in StageSettings. If error level is greater than 1, we just don't sync
typedef enum {
	kMCSStageStageErrorLevelGood = 0,
	kMCSStageStageErrorLevelRecoverable = 1,
    kMCSStageStageErrorLevelMultiple = 2,
    kMCSStageStageErrorLevelSerious = 3,
    kMCSStageStageErrorLevelUnrecoverable = 4,
    kMCSStageStageErrorLevelUnexpected = 100
} MCSStageStateErrorLevel;

extern NSString *kMCSRStageStateErrorLevelKey;
extern NSString *kMCSRStageStateErrorLevelDescription;



typedef enum  {
    kMCSReplicaCachedValueConflictType = 1,
    kMCSReplicaCheckpointConflictType = 2
} MCSReplicaConflictType;


typedef enum {
	kMCSROfflineStatusUndefined = -1,
	kMCSROfflineStatusNormal = 0,
	kMCSROfflineStatusWrongEnvironment = 1,
	kMCSROfflineStatusInTrial = 2,
	kMCSROfflineStatusWiped = 3
} MCSROfflineStatus;


// Error Masks
#define kMCSRErrorCodeMask      0x000000FF
#define kMCSRErrorClassMask     0x0000FF00
#define kMCSRErrorFlagMask      0x00FF0000

// Error flags
enum {
	// These flags denote error condition codes coming from elsewhere
	kMCSRErrorFlagFramework   = 0x00010000, // an error provided by framework
	kMCSRErrorFlagRemote      = 0x00020000, // an error provided by remote side during sync; not to be confused with kMCSRErrorClassRemoteDB
};

// Error classes
enum {
	kMCSRErrorClassNone       = 0x00000000, // not used; not really an error, or malformed error
	kMCSRErrorClassIO         = 0x00001000, // errors related to communications via stdin or stdout
	kMCSRErrorClassFiles      = 0x00001100, // errors while reading or writing files
	kMCSRErrorClassAuthServer = 0x00001200, // errors while trying to connect to the auth server
	kMCSRErrorClassRemoteDB   = 0x00001300, // errors related to the postgres shared server
	kMCSRErrorClassLocalDB    = 0x00001400, // errors related to the postgres personal server 
	kMCSRErrorClassCritical   = 0x00001500, // out of memory or other extreme conditions
	
	// Add more as needed
	
	kMCSRErrorClassUnknown    = 0x0000FF00  // catch-all; try to add new classes instead of using Unknown class
};

// Error Condition Codes
enum {
	kMCSRErrorNone = 0,
	kMCSRErrorMissingAuthInfo,
	
	kMCSRErrorServerNotFound,
	kMCSRErrorProtocolUnsupported,
	kMCSRErrorConnectionFailed,
	kMCSRErrorInterrupted,
	
	kMCSRErrorSQL,
	kMCSRErrorReconcileFailed, // obsolete
	kMCSRErrorImportFailed,    // obsolete
	// Add more as needed
	
	kMCSRErrorUnknown = 0x000000FF
};

typedef unsigned MCReplicaClientError;


// Replica Daemon Exit Codes
enum {
	kMCSRExitCodeOK,
	kMCSRExitCodeRecoverable,
	kMCSRExitCodeNotRecoverable,
	kMCSRExitCodeInitFailed
};


// Database connection settings
// - provided in archived dictionary on stdin at launch
extern NSString *kMCSRMasterDatabaseNameKey;
extern NSString *kMCSRServerAddressesKey; // array
extern NSString *kMCSRServerPortKey;
extern NSString *kMCSRUsernameKey;
extern NSString *kMCSRPasswordKey;
extern NSString *kMCSRMasterConnectionInfoKey;
extern NSString *kMCSRCloudUsernameKey;


// Distributed Notification names and user info dictionary keys
extern NSString *kMCSChangedObjectURIsKey;

extern NSString *kMCSRWillCreateDatabaseNotificationName;
extern NSString *kMCSRCopyStartedNotificationName;
extern NSString *kMCSRCopyProgressNotificationName;
extern NSString *kMCSRCopyFinishedNotificationName;
extern NSString *kMCSRDatabaseReadyNotificationName;
extern NSString *kMCSRSyncStartedNotificationName;
extern NSString *kMCSRSyncFinishedNotificationName;
extern NSString *kMCSRSyncFailedNotificationName;
extern NSString *kMCSRSyncProgressNotificationName;

extern NSString *kMCSRSourceDatabaseRowCountKey;
extern NSString *kMCSRRowsCopiedKey;
extern NSString *kMCSRCurrentTableNameKey;
extern NSString *kMCSRCurrentTableNameRowCountKey;
extern NSString *kMCSRResultCodeKey; // NO == failure; YES == success
extern NSString *kMCSRErrorKey;
extern NSString *kMCSRCurrentlyProcessedKey;
extern NSString *kMCSRTotalChangesKey;


// included in sync finished notification
extern NSString *kMCSRClientChangesProcessedKey;
extern NSString *kMCSRServerChangesProcessedKey;
extern NSString *kMCSRServerAddressUsedKey;
extern NSString *kMCSRAuthErrorCodeKey;
extern NSString *kMCSRRemoteRefreshCandidates;

// included in the failure notification
extern NSString *kMCSRSyncFailureCodeKey;
extern NSString *kMCSRProcessIDKey;
extern NSString *kMCSRDatabaseIDKey;
extern NSString *kMCSRAuthResponsePayloadKey;

extern NSString *kMCSRSyncConnectionIdentifier;

extern NSString* MCReplicaUtilityDomain;

// Database user defaults
extern NSString *kMCSREnvironmentIDKey;
extern NSString *kMCSRSyncStatusKey; // store in the replicant info dictionary, which is keyed by the replicantUUID

extern NSString *kMCCloudHostKeychainURL;


@interface MCClientServerDefines : NSObject {

}

+ (MCSAuthenticationErrorCode)errorCodeForServerResponse:(MCSAuthorizationResultCode)response;
+ (NSError *)authenticationErrorForCode:(MCSAuthenticationErrorCode)errorCode;

+ (BOOL)userInterventionRequiredForAuthErrorCode:(MCSAuthenticationErrorCode)errorCode;
+ (BOOL)userInterventionRequiredForServerResponse:(MCSAuthorizationResultCode)response;

+ (NSError *)authenticationErrorForServerResponseCode:(MCSAuthorizationResultCode)response;
+ (NSError*)databaseListErrorForServerResponseCode: (MCSDatabaseListResultCode)responseCode;

+ (void)logDuration:(NSDate *)startDate level:(MCEventLogLevel)level taskDescription:(NSString *)description;

+ (NSString *)notificationObjectForClientUUID:(NSString *)clientUUID databaseName:(NSString *)dbName;

+ (NSString *)messageForClientStatus:(MCSReplicaStatus)status;

+ (NSString *)nameForErrorClass:(int)class;
+ (NSString *)nameForErrorCondition:(int)condition;
+ (NSString *)messageForReplicaSyncResultCode:(int)resultCode;

+ (Class)localizationClass; 
+ (void)setLocalizationClass:(Class)someClass;

@end
