//
//  BIDatabaseObjectContext.h
//  BISubstrate
//
//  Created by Eric Hochmeister on 16/08/06.
//  Copyright 2006 __MyCompanyName__. All rights reserved.
//

#import <MCFoundation/MCPDatabaseObjectContext.h>

@class BITaxManager;
@class BIQueryHandler;
@class BIIdleManager;
@class BIAllClientsSummary;
@class BIBEXIgnore;
@class BIUser;
@class BICategory;
@class BIClient;
@class ABPerson;
@class BICurrency;
@class BICurrencyRepresentation;
@class BIUser;
@class BITimeSlip;
@class BIProject;
@class CNContact;

#ifdef BILLINGS_PRO
@class BPDownloadManager;
@class BIIdentity;
@class BITimeEntry;
@class BIConnectorMap;
#endif

/*!
    @class       BIDatabaseObjectContext
    @abstract    BIDatabaseObjectContext is a subclass of MCPDatabaseObjectContext and is simply where we put Billings specific functionality.
    @discussion  BIDatabaseObjectContext is similar in a way to Document but from a Foundation standpoint.  You can get to most things in Foundation from BIDatabaseObjectContext, examples being the Tax Manager, Query Handler and the Idle Manager.
 
                 TO DO 
 
                 -----
 
                 sep 19, 2007 - elh - move objectsForEntityNamed:foreignAppName:foreignAppEntityName:... to QueryHandler.  I think the reason its here to start is because it resembled similar methods on the object context, ie. objectsForEntityNamed:... maybe it makes sense, but we should evaluate.
*/


@interface BIDatabaseObjectContext : MCPDatabaseObjectContext {

    BITaxManager* _taxManager;
    BIQueryHandler *_queryHandler;
    BIIdleManager* _idleManager;
	BIAllClientsSummary* _allClientsSummary;
	
	BPDownloadManager *_downloadManager;
	
	NSOperationQueue* _clientRefreshOperationQueue;

    BOOL _cacheRecalculationInProgress;
}

@property (nonatomic, assign, readonly) BOOL cacheRecalculationInProgress;

- (Class)creationContextClass;

- (BIUser *)currentUser;

- (BITaxManager*)taxManager;
- (void)setTaxManager:(BITaxManager*)taxManager;

- (BIQueryHandler*)queryHandler;
- (void)setQueryHandler:(BIQueryHandler*)hQuery;

- (BIIdleManager*)idleManager;
- (void)setIdleManager:(BIIdleManager*)idleManager;

- (BIAllClientsSummary *)allClientsSummary;
- (void)setAllClientsSummary:(BIAllClientsSummary *)anAllClientsSummary;

- (NSArray*)objectsForEntityNamed:(NSString*)anEntityName 
                   foreignAppName:(NSString*)anAppName
             foreignAppEntityName:(NSString*)anAppEntityName
               foreignAppImportID:(NSString*)foreignID;

- (id)objectForEntityNamed:(NSString*)anEntityName 
            foreignAppName:(NSString*)anAppName
      foreignAppEntityName:(NSString*)anAppEntityName
        foreignAppImportID:(NSString*)foreignID;

//- (NSArray*)objectsForEntityNamed:(NSString*)anEntityName 
//                   foreignAppName:(NSString*)anAppName
//             foreignAppEntityName:(NSString*)anAppEntityName
//               foreignAppImportID:(NSString*)foreignID
//                         invoiced:(BOOL)isInvoiced;
//
//- (id)objectForEntityNamed:(NSString*)anEntityName 
//            foreignAppName:(NSString*)anAppName
//      foreignAppEntityName:(NSString*)anAppEntityName
//        foreignAppImportID:(NSString*)foreignID
//                  invoiced:(BOOL)isInvoiced;

- (BIBEXIgnore*)insertObjectIntoBEXIgnore:(id)anObj;

- (BIUser *)userWithNameLike:(NSString *)aName createIfNotFound:(BOOL)flag;
- (BICategory *)categoryWithNameLike:(NSString *)aName createIfNotFound:(BOOL)flag;

- (void)replaceReferencesToUser:(BIUser *)aOldUser withUser:(BIUser *)aNewUser;


// build from members and conflicts
- (void)refreshClients;

- (BIClient *)createClientWithABPerson:(ABPerson *)aPerson;

/**
 Create a new BIClient by importing data from a CNContact.
 
 This is the modern replacement for -createClientWithABPerson: using the Contacts framework.
 Creates a new client and imports contact data (name, email, address, etc.) from the provided contact.
 
 @param contact The CNContact to import data from. Must not be nil.
 @return A newly created BIClient with imported contact data, inserted into this context.
 
 @note This is import-only. No link or sync relationship is created with the system contact.
 
 @code
 CNContact *contact = // get from BIContactStoreManager or VCF file
 BIClient *client = [context createClientFromContact:contact];
 [context saveChanges];
 @endcode
 */
- (BIClient *)createClientFromContact:(CNContact *)contact;

- (void)recordCurrencyChangeFrom:(BICurrency *)oldCurrency 
							  to:(BICurrency *)newCurrency 
					   forClient:(BIClient *)aClient;

- (BICurrency *)changeBaseCurrencyToCurrencyRepresentation:(BICurrencyRepresentation *)rep applyToClients:(BOOL)apply;

- (BOOL)areClientsUsingMultipleCurrenciesOrNotBase:(NSArray *)someClients;

// returns that single currency or nil otherwise (no currency or multi)
- (BICurrency *)singleCurrencyFromObjects:(NSArray *)someObjects;
- (BOOL)areObjectsUsingSingleCurrency:(NSArray *)someObjects;

/**
 Checks for any cache values cleared out as a result from a sync. If so then it forces the object to recalculate it and ensures
 that the changes will not be sent over in the next sync.
 */
- (void)changeLogTableCleanup;

#ifdef BILLINGS_PRO

/*!
 Returns the timeEntry if there is one registered in the defaults.
 Pass nil to clear the setting
 */
- (BITimeEntry *)activePunchcardTimeEntryForCurrentUser;
- (void)setActivePunchcardTimeEntryForCurrentUser:(BITimeEntry *)anEntry;

/*!
 Derived from the active punchcard time entry
 */

- (BITimeSlip *)activePunchcardTimeSlipForCurrentUser;

- (BITimeEntry *)startPunchcardTimerForTimeSlip:(BITimeSlip *)aSlip;
- (void)stopActivePunchcardTimer;

- (long)durationOfActivePunchcardTimeslip;

- (long)startTimeOfActivePunchcardTimeslip;


- (BIIdentity *)defaultIdentityCreateIfNeeded;

- (BPDownloadManager *)downloadManager;

- (BITimeSlip *)createTimeSlipOfType:(int)aTypeCode 
					 inProjectWithID:(NSNumber *)aProjectID;

- (long)addTimeToTimeslip:(NSNumber *)aSlipID 
				withSeconds:(NSNumber *)seconds;

- (BOOL)deletePunchcardWorkingSlipWithID:(NSNumber *)aSlipID;



/*!
 Returns the current user generated unique number for the entity - formatted based on scheme
- (NSString *)formattedUserUniqueNumberForEntity:(NSString *)entName scheme:(BPNextUniqueNumberingScheme)aScheme format:(NSString *)format;

 Increments the current unique number by one, saves it and then formats it and returns it.

- (NSString *)formattedNextUserUniqueNumberForEntity:(NSString *)entName scheme:(BPNextUniqueNumberingScheme)aScheme format:(NSString *)format;
*/


/*!
 Returns the number of changes that have to go to the server.
 */
- (NSInteger)pendingChangesCountToBeSyncedToServer;

/*!
 The number of PDFs that have to be sent to the server
 */
- (NSInteger)pendingUploadsToBeSentToServer;

/*!
 Finds slips modified in the last x days and recalculates if needed
 */
- (void)recalculateCachedValuesIfNeededModifiedInLastDays:(NSInteger)days;

/**
 Used to calculate cache values for TimeSlips, Projects, and Clients
 */
- (void)recalculateCachedValuesIfNeeded;


/*!
 Gets the archivableRepresentation from the object and copies it to the uploads folder. Create a url ref that will reference the file storage
 */
- (BOOL)storeArchivableRepresentationOfObject:(MCPObject *)obj error:(NSError **)error;

/*!
 Takes a dictionary as generated from MCPObject -archivableRepresentation and re-inserts or updates the objects.
 */
- (void)restoreObjectsFromArchivableRepresentation:(NSDictionary *)dict;


#endif
@end

@interface BIDatabaseObjectContext (Migration)
// to support worker labels
- (void)convertForeignAppUserToUser;
- (void)createBaseCurrencyIfNeeded;

- (void)removeDuplicateUsers;

#ifdef BILLINGS_PRO
- (void)migrateIdentityFromDefaultsAndSupportFolder:(NSString *)aPath;
- (void)migratePDFsIntoFileStorageUsingBasePath:(NSString *)aPath;

// returns an array of migrated url references
- (NSArray *)migratePDFsIntoBillingsProAndCloudUploadUsingBasePath:(NSString *)aPath errors:(NSMutableArray *)errors;
- (void)absorbReportTemplatesWithExtension:(NSString *)aExt fromFolder:(NSString *)aSourcePath;

// given an array of already migrated file references, migrates the remaining (from DBAlias to a string path)
- (void)migrateFileReferencePathsFromAliasesMinus:(NSArray *)alreadyMigrated errors:(NSArray **)errs;


- (BIConnectorMap *)createConnectorMapForObject:(id)obj foreignApp:(NSString *)fAppName
							  foreignEntityType:(NSString *)aType
									  foreignID:(NSString *)someValue;


#endif


@end

