#import "EditTabController.h"
#import "Accessors.h"
#import "ConnectionPair.h"
#import "OACategories.h"
#import "OACoreData.h"
#import "OADebug.h"

@interface EditTabController (Private)
- (void) setFilterPredicate:(NSString*)text;
@end

@implementation EditTabController

- init
{
    [super init];
    a_connectionPairs = [[NSMutableArray alloc] init];
    a_newWordText = @"";
    return self;
}

- (void) dealloc
{
    [a_connectionPairs release];
    [a_newWordText release];
    [super dealloc];
}

- (void) awakeFromNib
{
    m_predicateTemplate = [[NSPredicate predicateWithFormat:@"text BEGINSWITH[cd] $TEXT"] retain];
    
    ConnectionPair *cp = [[[ConnectionPair alloc] init] autorelease];
    [cp setRelationshipType:[m_dictionary relationshipForEquivalence]];
    [self setConnectionPairs:[NSMutableArray arrayWithObject:cp]];

    // Try to pre-set the user and targetLanguage fields.
    NSArray *users = [[m_dictionary managedObjectContext] allObjectsOfEntityType:@"User"];
    if ([users count] != 0) {
        [self setUser:[users objectAtIndex:0]];

        NSMutableArray *langs = 
            [NSMutableArray arrayWithArray:
                [[m_dictionary managedObjectContext] allObjectsOfEntityType:@"Language"]];
        [langs removeObject:[[self user] nativeTongueValue]];
        if ([langs count] != 0)
            [self setTargetLanguage:[langs objectAtIndex:0]];
    }    
}

GETSETIMPLRETAIN(NSMutableArray *, connectionPairs, ConnectionPairs);
GETSETIMPLRETAIN(NSManagedObject *, user, User);
GETSETIMPLRETAIN(NSManagedObject *, targetLanguage, TargetLanguage);
//GETSETIMPLCOPY(NSString *, newWordText, NewWordText)

- (NSString*) newWordText
{
    return a_newWordText;
}

- (void) setNewWordText:(NSString*)text
{
    a_newWordText = [text copy];
}

#pragma mark -
#pragma mark Adding words and relationships

- (IBAction) add:(id)sender
{
    NSManagedObject *nativeTongue = [[self user] nativeTongueValue];
    NSManagedObject *targetLanguage = [self targetLanguage];
    NSString *mainText = [[self newWordText] strip];
    if ([mainText isEqual:@""]) return; // ignore words that consist only of spaces!
    NSManagedObject *mainWord = [m_dictionary wordWithText:mainText
                                                  language:targetLanguage];
    
    // update the "creation date", which affects quizzes:
    [m_dictionary touchWord:mainWord];

    // iterate over the connections we are supposed to create to this word:
    FOREACH(ConnectionPair *, cp, [self connectionPairs]) {
        NSManagedObject *relationshipType = [cp relationshipType];
        NSString *otherWordText = [[cp wordText] strip];
        if (otherWordText == nil || [otherWordText isEqual:@""]) continue; // ignore empty text
        BOOL interlanguage = [relationshipType interlanguageBool];
        
        // create the other word in the appropriate language
        NSManagedObject *otherLanguage = (interlanguage ? nativeTongue : targetLanguage);
        NSManagedObject *otherWord = [m_dictionary wordWithText:otherWordText language:otherLanguage];        
        
        // connect the words: note that interlanguage connections are bi-directional
        [m_dictionary connectWord:mainWord toWord:otherWord relationship:relationshipType];
        if (interlanguage)
            [m_dictionary connectWord:otherWord toWord:mainWord relationship:relationshipType];
        
        // clear out the word text in preparation for the next round
        [cp setWordText:@""];
    } ENDFOREACH;

    // reset the filter predicate, causing the array controller to reload its data
    [self setFilterPredicate:mainText];    
    
    // return the focus to the "main word" text box:
    [[m_dictionary mainWindow] makeFirstResponder:m_mainTextField];
}

#pragma mark -
#pragma mark Coordinating the user interface

- (void) setFilterPredicate:(NSString*)text
{
    NSDictionary *dict = [NSDictionary dictionaryWithObject:text forKey:@"TEXT"];
    NSPredicate *pred = [m_predicateTemplate predicateWithSubstitutionVariables:dict];
    [m_words setFilterPredicate:pred];    
}

- (void) chooseKeyboardFor:(NSManagedObject*)language
{
    if (language) {
        NSString *keylnm = [language keyboardLayoutValue];
        if (keylnm && ![keylnm isEqual:@""]) {
            // For reasons I fail to completely understand, this sometimes gets recursively
            // invoked: in that case we don't overwrite the original saved layout
            if (m_oldLayout == nil)
                m_oldLayout = [[OAKeyboardLayout currentKeyboardLayout] retain];
            OAKeyboardLayout *keyl = [OAKeyboardLayout keyboardLayoutWithName:keylnm];
            [keyl set];
            OALog(@"Switching to keyboard layout: %@", keylnm);
        }
    }
}

- (void) resetKeyboard
{
    if (m_oldLayout) {
        OALog(@"Reverting to keyboard layout: %@", [m_oldLayout name]);
        [m_oldLayout set];
        [m_oldLayout release];
        m_oldLayout = nil;
    }
}

- (BOOL)tableView:(NSTableView *)aTableView shouldEditTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
    OALog(@"tableView:%p shouldEditTableColumn:%@ row:%d", aTableView, [aTableColumn identifier], rowIndex);
    
    if ([[aTableColumn identifier] isEqual:@"text"]) {
        ConnectionPair *cp = [[self connectionPairs] objectAtIndex:rowIndex];
        NSManagedObject *rel = [cp relationshipType];
        OALog(@"  relationship type = %@", [rel nameValue]);
        BOOL interlanguage = [rel interlanguageBool];
        NSManagedObject *otherLanguage = (interlanguage ? [[self user] nativeTongueValue] : [self targetLanguage]);
        OALog(@"  otherLanguage = %@", [otherLanguage nameValue]);
        [self chooseKeyboardFor:otherLanguage];
    }
    
    return YES;
}

// these two methods are invoked by the "main word" text field
// because it is a subclass of OATextField.  I tried to use
// the control:textShouldBeginEditing: below, but it didn't seem to
// work at the right times.
- (void) becameFirstResponder:sender
{
    OALog(@"becameFirstResponder");
    if (sender == m_mainTextField)
        [self chooseKeyboardFor:[self targetLanguage]];
}

- (void) resignedFirstResponder:sender
{
    OALog(@"resignedFirstResponder");
    if (sender == m_mainTextField) 
        [self resetKeyboard];
}

/*
- (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor
{
    if (control == m_mainTextField) 
        [self chooseKeyboardFor:[self targetLanguage]];

    return YES;
}

- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
{
    [self resetKeyboard];

    return YES;
}
*/

// This gets invoked when the user starts editing the text of 
// a word.  In this case we clear any selections from the 
// table views because otherwise weird behavior results where
// the current entry in the table view gets reselected as the
// control text changes and then gets set as the user's choice,
// etc.
- (void) controlTextDidBeginEditing:(NSNotification *)aNotification
{
    [m_words setSelectionIndex:NSNotFound];
}

// This gets invoked when the text in the "main word" 
// NSTextField changes, because we are its delegate.
- (void) controlTextDidChange:(NSNotification *)aNotification 
{        
    NSTextField *textField = [aNotification object];    
    if (textField == m_mainTextField) {
        NSString *text = [[textField stringValue] copy];
        if ([text length] == 0)
            [m_words setFilterPredicate:nil];
        else  {
            [self setFilterPredicate:text];
        }
    }
}

// Invoked when the user selects something from the "main words" box.
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
{
    NSTableView *table = [aNotification object];
    if (table == m_wordsTableView) {
        int numselrows = [table numberOfSelectedRows];    
        if (numselrows > 0) {
            NSString *seltext = [[m_words selectedObject] textValue];
            [self setNewWordText:seltext];
            
            NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:0];
            [m_relationshipTableView selectRowIndexes:indexSet byExtendingSelection:NO];
            [m_relationshipTableView editColumn:1 row:0 withEvent:nil select:YES];
        }
    }
}


@end
