//
//  PayeeManagement.m
//  drachma
//
//  Created by Niko Matsakis on 7/21/06.
//  Copyright 2006 __MyCompanyName__. All rights reserved.
//

#import "DrachmaPayeeManagement.h"
#import "OACoreData.h"
#import "ModeledObjectTypes.h"
#import "OAMacros.h"
#import "OACategories.h"

@interface NSManagedObjectContext (PayeeManagementInternal)
- (NSArray*) i_unusedPayees;
@end

@implementation NSManagedObjectContext (PayeeManagement)

- (NSArray*) i_payeesNamed:(NSString*)name
{
    DEFINEARRAYQUERY(@"Payee", @"name BEGINSWITH[c] %@", name);
}

- (NSArray*) i_categoriesNamed:(NSString*)catName
{
    DEFINEARRAYQUERY(@"Category", @"name == %@", catName);
}

- (NSArray*) i_unusedPayees
{
    DEFINEARRAYQUERY(@"Payee", @"expenses[SIZE] == 0", nil);
}

- (Payee*)payeeNamed:(NSString*)payeeName
{
    
    // Find an existing payee object with the same name,
    // but ignoring case.  Note that there is no way to do
    // a query like ==[c] so we have use this hack.
    NSArray *possiblePayees = [self i_payeesNamed:payeeName];
    Payee *payee = nil;    
    FOREACH(Payee *, possiblePayee, possiblePayees) {
        if ([[possiblePayee name] isEqualToStringIgnoringCase:payeeName])
            payee = possiblePayee;
    } ENDFOREACH;
    
    // If none was found, creat a new Payee.
    if (payee == nil) {
        payee = [NSEntityDescription insertNewObjectForEntityForName:@"Payee"
                                              inManagedObjectContext:self];
        [payee setName:payeeName];
        NSLog(@"New payee created: %@", payeeName);
    }
    
    return payee;
}

- (Category*)categoryNamed:(NSString*)catName
{
    NSArray *categories = [self i_categoriesNamed:catName];
    if ([categories count] == 0) {
        Category *cat = [NSEntityDescription insertNewObjectForEntityForName:@"Category"
                                                      inManagedObjectContext:self];
        [cat setName:catName];
        return cat;
    }
    return [categories objectAtIndex:0];
}

@end

@implementation Drachma (PayeeManagement)

- (void) initPayeeManagement
{
    NSManagedObjectContext *mctx = [self managedObjectContext];
    NSNotificationCenter *ncenter = [NSNotificationCenter defaultCenter];
    [ncenter addObserver:self 
                selector:@selector(payeeTrackChanges:) 
                    name:NSManagedObjectContextObjectsDidChangeNotification 
                  object:mctx];
}

- (void) purgeDuplicatePayees
{
    // Find payees with the same name but different case and remove
    // all but one of them (they SHOULD never exist, but older code 
    // had problems):
    NSManagedObjectContext *mctx = [self managedObjectContext];
    NSArray *payees = [mctx allObjectsOfEntityType:@"Payee"];
    NSMutableDictionary *payeeDict = [NSMutableDictionary dictionary];
    BOOL duplicates=NO;
    FOREACH(Payee *, payee, payees) {
        NSString *payeeName = [[payee name] lowercaseString];
        NSMutableArray *array = [payeeDict objectForKey:payeeName];
        if(array == nil) {
            array = [NSMutableArray array];
            [payeeDict setObject:array forKey:payeeName];
        }
        else duplicates=YES;
        [array addObject:payee];
    } ENDFOREACH;    
    if (duplicates) {
        FOREACH(NSArray *, payeeDups, [payeeDict allValues]) {
            if ([payeeDups count] < 2)
                continue;
            Payee *original = nil;
            FOREACH(Payee *, payee, payeeDups) {
                if (original == nil) {
                    original = payee;
                }
                else {
                    NSSet *expenses = [[payee mutableSetValueForKey:@"expenses"] copy];
                    FOREACH(Expense *, expense, expenses) {
                        [expense i_setPayee:original];
                    } ENDFOREACH;
                    NSLog(@"Purging duplicate payee:%@ (original:%@)", [payee name], [original name]);
                    [[self managedObjectContext] deleteObject:payee];
                }
            } ENDFOREACH;
        } ENDFOREACH;
    }
}

- (void) deallocPayeeManagement
{
    NSNotificationCenter *ncenter = [NSNotificationCenter defaultCenter];
    [ncenter removeObserver:self];
}

// Any time we detect changes, check for Payees that have no
// remaining expenses and delete them.
- (void) payeeTrackChanges:(NSNotification*)changes
{
    /*
    NSArray *unusedPayees = [[self managedObjectContext] i_unusedPayees];
    if ([unusedPayees count] > 0) {
        NSManagedObjectContext *mctx = [self managedObjectContext];
        FOREACH(Payee *, payee, unusedPayees) {
            assert ([payee countOfExpenses] == 0);
            [mctx deleteObject:payee];
        } ENDFOREACH;
    }
     */
    
    NSManagedObjectContext *mctx = [self managedObjectContext];
    NSArray *payees = [mctx allObjectsOfEntityType:@"Payee"];
    FOREACH(Payee *, payee, payees) {
        if ([[payee valueForKey:@"expenses"] count] == 0)
            [mctx deleteObject:payee];
    } ENDFOREACH;
}

@end
