//
//  MCObjectContextPool.h
//  MCClientServer
//
//  Created by Brent Gulanowski on 10-11-17.
//  Copyright 2010 Marketcircle Inc. All rights reserved.
//


@class MCPDatabaseObjectContext, MCHostingNode, MCObjectContextPoolRegistration;

/*!
    @enum		MCObjectContextUsage
    @abstract   Identifies the usage of object context.
    @discussion Helps the MCPObjectContext pool to decide how long the ObjectContext should be kept around.
    @constant   MCObjectContextLightUsage
	@constant   MCObjectContextNeutralUsage
	@constant   MCObjectContextHeavyUsage
	
*/

typedef enum {
	MCObjectContextLightUsage,
	MCObjectContextNeutralUsage,
	MCObjectContextHeavyUsage,
} MCObjectContextUsage;


/*!
    @protocol	MCObjectContextPoolClient
    @abstract   The MCObjectContextPoolClient Protocol must be implemented by every object that want to use the MCObjectContext Pool 
*/

@protocol MCObjectContextPoolClient<NSObject>

@required
/*!
    @function	- (void)objectContextReady:(MCPDatabaseObjectContext *)aContext forCloudAccount:(NSString *)cloudAccount;
    @abstract   Callback for a MCObjectContextPoolClient that a ObjectContext is ready to use. 
*/

- (void)objectContextReady:(MCPDatabaseObjectContext *)aContext forCloudAccount:(NSString *)cloudAccount userInfo:(id)userInfo;

@optional
/*!
 @function	- (MCObjectContextUsage)defaultUsage;
 @abstract  Returns a default usage for the MCObjectContextPoolClient if the MCObjectContextPoolClient returns a ObjectContext to the pool,
			the pool will try to ask the client to the default usage, if this method is not implemented the pool will assume a MCObjectContextNeutralUsage
 */
- (MCObjectContextUsage)defaultUsage;

- (NSUInteger)maxAccountsPerCloudAccount;

@end

@protocol MCObjectContextFactory<NSObject>

/*!
    @function	createObjectContext
    @abstract   Returns a initalized MCPDatabaseObjectContext with (if needed) a database connection
    @discussion The database connection should be configured and ready to use, but not connected. 
				The MCPObjectContextPool will ask the connection to connect. If the MCPObjectContext pool doensn't need to connect the 
				database connection, set establishDatabaseConnectionForObjectContext on the MCPObjectContext to false.
    @result     A initalized MCPDatabaseObjectContext with a database connection
*/

- (MCPDatabaseObjectContext *)createObjectContext;

@end



@interface MCObjectContextPool : NSObject {
	
	NSTimer * cleanupTimer;
	
	MCHostingNode *hostingNode;
	
	id<MCObjectContextFactory> contextFactory;
	
	NSMutableDictionary *contextPools; // sets of object contexts keyed by cloud account name
	NSMutableDictionary *reservations; // sets of reserved oc's keyed by cloud account name
	NSMutableDictionary *retiredContexts; // sets of OCs keyed by cloud account name - to be released
	NSMutableDictionary *requestQueues;
	
	BOOL establishDatabaseConnectionForObjectContext;
	
	@private NSUInteger lightUsageScore;
	@private NSUInteger neutralUseageScore;
	@private NSUInteger heavyUsageScore;
	@private NSUInteger trashUsageScore;
}

@property (retain) MCHostingNode *hostingNode;
@property (retain) id<MCObjectContextFactory> contextFactory;
@property (readwrite) BOOL establishDatabaseConnectionForObjectContext;
@property (readwrite) NSUInteger trashUsageScore;
// If you don't want to use the pool's pooling services, just it's creation abilities, use this
- (MCPDatabaseObjectContext *)createObjectContextForCloudAccount:(NSString *)cloudAccount;

- (void)requestObjectContextForCloudAccount:(NSString *)cloudAccount client:(id<MCObjectContextPoolClient>)client userInfo:(id)userInfo;
- (void)cancelRequestForClient:(id<MCObjectContextPoolClient>)client cloudAccount:(NSString *)cloudAccount;
- (void)returnObjectContext:(MCPDatabaseObjectContext *)aContext cloudAccount:(NSString *)cloudAccount client:(id <MCObjectContextPoolClient>)client;
- (void)returnObjectContext:(MCPDatabaseObjectContext *)aContext cloudAccount:(NSString *)cloudAccount client:(id <MCObjectContextPoolClient>)client usage:(MCObjectContextUsage)usage;

- (NSUInteger)poolSizeForCloudAccount:(NSString *)cloudAccount;
- (NSUInteger)numberOfUnusedObjectContextsForCloudAccount:(NSString *)cloudAccount;
- (NSUInteger)numberOfUsedObjectContextsForCloudAccount:(NSString *)cloudAccount;

@end
