/*
 Flash: Flashcard program
 Copyright (C) 2005, Niko Matsakis (niko@alum.mit.edu)
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#import "Accessors.h"
#import "Preferences.h"
#import "OADebug.h"

@implementation NSManagedObject (FlashExtensions)

#pragma mark -
#pragma mark Access

- (id) vkp:(NSString*)kp // shorter version of "valueForKeyPath:"
{
    return [self valueForKeyPath:kp];
}

- (NSManagedObject*) answerLanguageValue
{
    return [self valueForKey:@"answerLanguage"];
}

- (NSDate*) askNextOnValue
{
    return [self valueForKey:@"askNextOn"];
}

- (NSManagedObject*) articleValue
{
    return [self valueForKey:@"article"];
}

- (NSDate*) creationDateValue
{
    return [self valueForKey:@"creationDate"];
}

- (NSManagedObject*) connectionValue
{
    return [self valueForKey:@"connection"];
}

- (NSSet*) connectionsFromValue
{
    return [self valueForKey:@"connectionsFrom"];
}

- (NSSet*) connectionsToValue
{
    return [self valueForKey:@"connectionsTo"];
}

- (NSManagedObject*) dualValue
{
    return [self valueForKey:@"dual"];
}

- (NSManagedObject*) fromValue
{
    return [self valueForKey:@"from"];
}

- (NSNumber*) idValue
{
    return [self valueForKey:@"id"];
}

- (BOOL) interlanguageBool
{
    return [[self interlanguageValue] intValue] != 0;
}

- (NSNumber*) interlanguageValue
{
    return [self valueForKey:@"interlanguage"];
}

- (NSString*) keyboardLayoutValue
{
    NSString *res = [self valueForKey:@"keyboardLayout"];
    if (res) return res;
    return @"";
}

- (NSManagedObject*) languageValue
{
    return [self valueForKey:@"language"];
}

- (int) learnCountValue
{
    return [[self valueForKey:@"learnCount"] intValue];
}

- (NSSet*) learnedValue
{
    return [self valueForKey:@"learned"];
}

- (NSString*) nameValue
{
    return [self valueForKey:@"name"];
}

- (NSManagedObject*) nativeTongueValue
{
    return [self valueForKey:@"nativeTongue"];
}

- (NSManagedObject*) quizLanguageValue
{
    return [self valueForKey:@"quizLanguage"];
}

- (int) quizLengthValue
{
    return [[self valueForKey:@"quizLength"] intValue];
}

- (int) quizDirectionValue
{
    return [[self valueForKey:@"quizDirection"] intValue];
}

- (BOOL) readyForUseValue
{
    return [[self valueForKey:@"readyForUse"] intValue];
}

- (NSManagedObject*) referenceLanguageValue
{
    return [self valueForKey:@"referenceLanguage"];
}

- (NSManagedObject*) relationshipValue
{
    return [self valueForKey:@"relationship"];
}

- (int) stageValue
{
    return [[self valueForKey:@"stage"] intValue];
}

- (NSString*) textValue
{
    return [self valueForKey:@"text"];
}

- (NSString*) textAtLastArticleUpdateValue
{
    return [self valueForKey:@"textAtLastArticleUpdate"];
}

- (NSManagedObject*) toValue
{
    return [self valueForKey:@"to"];
}

- (NSManagedObject*) typeValue
{
    return [self valueForKey:@"type"];
}

- (NSManagedObject*) userValue
{
    return [self valueForKey:@"user"];
}

- (NSManagedObject*) wordValue
{
    return [self valueForKey:@"word"];
}

- (int) modelVersionValue
{
    return [[self valueForKey:@"modelVersion"] intValue];
}

#pragma mark -
#pragma mark Assignment

- (void) setArticleValue:(NSManagedObject*) articleValue
{
    [self setValue:articleValue forKey:@"article"];
}

- (void) setAskNextOnValue:(NSDate*)value
{
    [self setValue:value forKey:@"askNextOn"];
}

- (void) setCreationDateValue:(NSDate*)value
{
    [self setValue:value forKey:@"creationDate"];
}

- (void) setConnectionValue:(NSManagedObject*) connValue
{
    [self setValue:connValue forKey:@"connection"];
}

- (void) setDualValue:(NSManagedObject*)obj
{
    return [self setValue:obj forKey:@"dual"];
}

- (void) setFromValue:(NSManagedObject*)word
{
    [self setValue:word forKey:@"from"];
}

- (void) setLanguageValue:(NSManagedObject*)lang
{
    [self setValue:lang forKey:@"language"];
}

- (void) setModelVersionValue:(int)newver
{
    [self setValue:[NSNumber numberWithInt:newver] forKey:@"modelVersion"];
}

- (void) setQuizValue:(NSManagedObject*)rel
{
    [self setValue:rel forKey:@"quiz"];
}

- (void) setReadyForUseValue
{
    [self setValue:[NSNumber numberWithBool:YES] forKey:@"readyForUse"];
}

- (void) setRelationshipValue:(NSManagedObject*)rel
{
    [self setValue:rel forKey:@"relationship"];
}

- (void) setStageValue:(int)value
{
    [self setValue:[NSNumber numberWithInt:value] forKey:@"stage"];
}

- (void) setTextValue:(NSString*)text
{
    [self setValue:text forKey:@"text"];
}

- (void) setTextAtLastArticleUpdateValue:(NSString*)text
{
    [self setValue:text forKey:@"textAtLastArticleUpdate"];
}

- (void) setToValue:(NSManagedObject*)word
{
    [self setValue:word forKey:@"to"];
}

- (void) setTypeValue:(NSManagedObject*)rel
{
    [self setValue:rel forKey:@"type"];
}

- (void) setUserValue:(NSManagedObject*)user
{
    [self setValue:user forKey:@"user"];
}

- (void) adjustAskNextOnFromStage
{
	int stage = [self stageValue];
	
	// Determine the interval until we ask again.
	const NSTimeInterval onehour = 60 * 60;
	const NSTimeInterval oneday = onehour * 24;
	
	NSTimeInterval interval;
	if (stage == -1) {
		// After a negative answer, we set the stage to -1 and re-ask the word after 22 hours.
		// Why 22?  The idea is that if they take their quiz "in the morning", they will get 
		// asked again in the morning.  This gives people some lee-way in when they take their 
		// quiz.  Could do it better if I was less lazy, I guess.
		interval = oneday - 2*onehour;
	} else {
		// After a positive answer, we wait 2^N days, where N is the number of times the word
		// has been answered correcntly in a row, up to a configurable maximum.
		interval = oneday;
		for (int i = 0; i < stage; i++)
			interval *= 2;
		
		int maxdays = [[Preferences sharedPreferences] maxDays];
		NSTimeInterval maxInterval = maxdays * oneday;
		if (interval > maxInterval)
			interval = maxInterval;
	}
	OALog (@"stage=%d and interval=%f or %f days", stage, interval, interval/oneday);
	
	/* Adjust when to next ask for this word and it's current "stage" */
	NSDate *nextask = [NSDate dateWithTimeIntervalSinceNow:interval];
	[self setAskNextOnValue:nextask];
	OALog (@"adjusted next ask to %@ based on stage == %d", [nextask description], stage);
}

#pragma mark -
#pragma mark Other

// Intended to be called on Connection objects.  Returns true if
// its type is contained in the set passed to it.
- (NSNumber*) typeOfRelationshipIsContainedIn:(NSSet *)set
{
    if ([set containsObject:[self typeValue]]) {
        return [NSNumber numberWithBool:YES];
    }
    return [NSNumber numberWithBool:NO];
}

- (NSNumber*) isNotDeletedObject
{
    return [NSNumber numberWithBool:![self isDeleted]];
}

#pragma mark -
#pragma mark Sorting

- (NSComparisonResult) compareByAskNextOnDate:(NSManagedObject*)otherLearning
{
    NSDate *myDate = [self askNextOnValue];
    NSDate *theirDate = [otherLearning askNextOnValue];
    return [myDate compare:theirDate];
}

@end