//
//  MCSyncAbstractObjectProcessor.h
//  GWSyncServices
//
//  Created by Michael Clark on 10/05/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
//

#import <Foundation/Foundation.h>

@class MCPObjectContext;
@class MCFileLogger;
@class MCSyncChange;

@interface MCSyncAbstractObjectProcessor : NSObject {

	MCPObjectContext*             __objectContext; // Not retained!
	MCFileLogger*                 __logger; // Only valid once a sync operation begins and invalid when it ends

	NSString*                     __clientSyncIdentifier;
	
	NSMutableDictionary*          __newObjectCache;
	NSMutableDictionary*          __deletedObjectCache;
}

- (id)initWithObjectContext: (MCPObjectContext*)objectContext clientSyncIdentifier: (NSString*)syncIdentifier logger: (MCFileLogger*)logger newObjectCache: (NSMutableDictionary*)newObjectCache deletedObjectCache: (NSMutableDictionary*)deletedObjectCache;

// SyncManager variants only check the instance cache for in-memory objects and if not found defers to SyncWorker
- (id)syncManagerProcessAddChange: (MCSyncChange*)change;
- (BOOL)syncManagerCommitObject: (id)object withAddChange: (MCSyncChange*)change;

- (id)syncManagerProcessModifyChange: (MCSyncChange*)change;
- (BOOL)syncManagerCommitObject: (id)object withModifyChange: (MCSyncChange*)change;

- (id)syncManagerProcessDeleteChange: (MCSyncChange*)change;
- (BOOL)syncManagerCommitObject: (id)object withDeleteChange: (MCSyncChange*)change;

// SyncWorker variants perform fetches to the database to get objects
- (id)syncWorkerProcessAddChange: (MCSyncChange*)change;
- (BOOL)syncWorkerCommitObject: (id)object withAddChange: (MCSyncChange*)change;

- (id)syncWorkerProcessModifyChange: (MCSyncChange*)change;
- (BOOL)syncWorkerCommitObject: (id)object withModifyChange: (MCSyncChange*)change;

- (id)syncWorkerProcessDeleteChange: (MCSyncChange*)change;
- (BOOL)syncWorkerCommitObject: (id)object withDeleteChange: (MCSyncChange*)change;

- (void)syncManagerFinalizeCommit;
- (void)syncWorkerFinalizeCommit;
	// These methods are for subclassers - by default they do nothing

// Methods that give subclassers a chance to do things without having to possibly repeat code by subclassing the above methods.
- (BOOL)shouldAddChange: (MCSyncChange*)change isOnMainThread: (BOOL)onMainThread;
- (id)objectForAdditionWithChange: (MCSyncChange*)change isOnMainThread: (BOOL)inMainThread;

//- (BOOL)wasParentObjectDeletedForChange: (MCSyncChange*)change;
	// This method was added to handle the case of sub-objects not being faulted yet in the main thread, but the parent object has been and that parent object has been deleted.  Before this method the main thread would not process this delete properly and leave it for the sync worker which would just delete the object, put the proper thing to do (in Daylites case) is to not do anything and allow the trash to trash the object
- (BOOL)shouldPhysicallyDeleteObject: (id)object forChange: (MCSyncChange*)change isOnMainThread: (BOOL)inMainThread;
	// This method allows the objects delete to be accept as far as SS thinks, but prevents the app from actually deleting it - used with reminders as an example - an event in iCal could have 2 alerts, which map to the same reminder in Daylite, if a user deletes one of the alerts in iCal DL should disable that part of the reminder but not actually delete it

- (BOOL)shouldCommitDeleteObject: (id)object forChange: (MCSyncChange*)change;
	// Subclassers can override this method to prevent the object processor from actually telling the deletionHandler to delete the object
	// Daylite uses this to prevent Contacts and Organizations from being deleted from the DB, but rather removes them from the sync list when the user cannot delete the object
	// Sync maps are still deleted

- (BOOL)shouldSkipProcessingAndForceAcceptanceOfChange: (MCSyncChange*)change;

// Process methods should not dirty objects in a way that cannot be rolled back (i.e. additions does not matter because the added object is not put in the objectContext until committing, but for modified objects they should not be dirtied because they are already persistent and managed)
- (void)processChangesOnAddForObject: (id)object recordRepresentation: (NSDictionary*)record syncChange: (MCSyncChange*)change;
- (void)processChangesOnModifyForObject: (id)object recordRepresentation: (NSDictionary*)record syncChange: (MCSyncChange*)change;
- (void)processChangesOnDeleteForObject: (id)object syncChange: (MCSyncChange*)change;

- (void)commitChangesOnAddForObject: (id)object recordRepresentation: (NSDictionary*)record syncChange: (MCSyncChange*)change;
- (void)willCommitModifyForObject: (id)object recordRepresentation: (NSDictionary*)record syncChange: (MCSyncChange*)change;
- (void)commitChangesOnModifyForObject: (id)object recordRepresentation: (NSDictionary*)record syncChange: (MCSyncChange*)change;
- (void)commitChangesOnDeleteForObject: (id)object syncChange: (MCSyncChange*)change;

@end
