//
//  RecipeActionTests.m
//  MealBuilder
//
//  Created by Phil Horowitz on 2/14/13.
//  Copyright (c) 2013 Phil Horowitz. All rights reserved.
//

#import "RecipeActionTests.h"
#import "RecipeAction.h"
#import "Measurements.h"

@interface RecipeActionTests()
@property (nonatomic, strong) NSDateFormatter *formatter;
@end

@implementation RecipeActionTests
-(void) setUp{
    self.formatter = [[NSDateFormatter alloc] init];
    [self.formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
}

-(NSDate *)get1970{
    return [self.formatter dateFromString:@"1970-01-01 12:00"];
}

-(void) testConvenienceInit{
    NSTimeInterval startingTime = 255;
    NSString *startingAction = @"Test Action";
    
    RecipeAction *testAction = [[RecipeAction alloc] initWithAction:startingAction withTime:startingTime];
    
    STAssertEquals(startingTime, testAction.time, @"RecipeAction convenience initializer should set time property");
    STAssertTrue( [startingAction isEqualToString:testAction.actionText], @"RecipeAction convenience initializer should set actionText property");
}

-(void)testComparison{
    RecipeAction *action1 = [[RecipeAction alloc] init];
    RecipeAction *action2 = [[RecipeAction alloc] init];
    NSDate *d1970 = [self get1970];
    action1.time = 10;
    action1.finishTime = d1970;
    action2.time = 20;
    action2.finishTime = d1970;
    
    STAssertTrue([action1 compare:action2] == NSOrderedDescending, @"Comparison operator doesn't accurately compare recipes");
    STAssertTrue([action2 compare:action1] == NSOrderedAscending, @"Comparison operator doesn't accurately compare recipes");
}

#pragma mark MinStartTime Tests
-(void) testStartTime{
    RecipeAction *testAction = [[RecipeAction alloc] init];
    testAction.time = 60; // 60 seconds in the past
    NSDate *startDate = [self get1970];
    testAction.finishTime = [self.formatter dateFromString:@"1970-01-01 12:01"];
    
    STAssertTrue( [testAction.minStartTime compare:startDate] == NSOrderedSame, @"Setting finishTime should accurately calculate instructionTime");
}

-(void) testStartTimeWithLargeNumber{
    RecipeAction *testAction = [[RecipeAction alloc] init];
    testAction.time = 86400; // 1 day prior
    
    NSDate *startDate = [self.formatter dateFromString:@"1970-01-01 12:00"];
    testAction.finishTime = [self.formatter dateFromString:@"1970-01-02 12:00"];
    
    STAssertTrue( [testAction.minStartTime compare:startDate] == NSOrderedSame, @"getStartTimeFromTime method isn't properly getting the time of 1 day prior");
}

-(void) testStartTimeChangesWhenNextActionChanges{
    RecipeAction *testAction = [[RecipeAction alloc] init];
    testAction.time = 60;
    testAction.finishTime = [self.formatter dateFromString:@"1970-01-01 12:02"];
    NSDate *initialStartTime = testAction.minStartTime;
    
    RecipeAction *nextAction = [[RecipeAction alloc] init];
    nextAction.time = 60;
    testAction.nextAction = nextAction;
    
    // test if startTime changes
    STAssertFalse([testAction.minStartTime compare:initialStartTime] == NSOrderedSame, @"Setting a new nextAction should change startTime");
    
    // test if startTime changes to what we expect
    NSDate *expectedStartTime = [self.formatter dateFromString:@"1970-01-01 12:00"];
    STAssertTrue( [testAction.minStartTime compare:expectedStartTime] == NSOrderedSame, @"Setting nextAction changed startTime to an unexpected value");
}

-(void) testStartTimeWithNextAction{
    RecipeAction *next = [[RecipeAction alloc] init];
    next.time = 50;
    RecipeAction *testAction = [[RecipeAction alloc] init];
    testAction.time = 10;
    testAction.nextAction = next;
    
    NSDate *startDate = [self.formatter dateFromString:@"1970-01-01 12:00"];
    testAction.finishTime = [self.formatter dateFromString:@"1970-01-01 12:01"];
    
    STAssertTrue( [testAction.minStartTime compare:startDate] == NSOrderedSame, @"getStartTimeFromTime method isn't properly considering the steps that come after it");
}

-(void)testStartTimeChangesWhenTimeChanges{
    RecipeAction *testAction = [[RecipeAction alloc] init];
    testAction.finishTime = [self.formatter dateFromString:@"1970-01-01 12:01"];
    
    NSDate *initialStartTime = testAction.minStartTime;
    testAction.time = 60;
    STAssertFalse( [testAction.minStartTime compare:initialStartTime] == NSOrderedSame, @"Setting time property doesn't change startTime");
    STAssertTrue([testAction.minStartTime compare:[self get1970]] == NSOrderedSame, @"Setting time property changes startTime unexpectedly");
    
}

-(void) testStartTimeIsNilWithNoEndDate{
    RecipeAction *testAction = [[RecipeAction alloc] init];
    testAction.time = 10;
    STAssertNil(testAction.minStartTime, @"Not setting finishTime should make startTime nil");
    
    testAction.finishTime = nil;
    STAssertNil(testAction.minStartTime, @"Setting finishTime to nil should make startTime nil");
}


#pragma mark MaxStartTimeTests
-(void) testMaxStartTime{
    RecipeAction *testAction = [[RecipeAction alloc] init];
    testAction.time = 30;
    testAction.expirationTime = 30;
    NSDate *now = [NSDate date];
    NSDate *compareDate = [[NSDate alloc] initWithTimeInterval:-60 sinceDate:now];
    testAction.finishTime = now;
    STAssertTrue([testAction.maxStartTime compare:compareDate] == NSOrderedSame, @"setting expirationTime and finishTime should set maxStartTime");
    
    testAction.time = 60;
    compareDate = [[NSDate alloc] initWithTimeInterval:-90 sinceDate:now];
    STAssertTrue([testAction.maxStartTime compare: compareDate] == NSOrderedSame, @"Setting time should re-calc maxStartTime");
    
    testAction.expirationTime = 60;
    compareDate = [[NSDate alloc] initWithTimeInterval:-120 sinceDate:now];
    STAssertTrue([testAction.maxStartTime compare:compareDate] == NSOrderedSame, @"Setting exipration time should re-calc maxStartTime");
}

#pragma mark TimeCalc tests
-(void) testTimeCalcPerUnit{
    RecipeAction *action= [[RecipeAction alloc] init];
    action.time = 10; // 10s per gram
    Unit *unit = [[Milliliter alloc] initWithAmount:100];
    TimePerUnit *tpu = [[TimePerUnit alloc] init];
    UnitContainer *container = [[UnitContainer alloc] initWithUnit:unit];
    tpu.unit = container;
    action.timeCalculator = tpu;
    
    NSDate *now = [NSDate date];
    NSDate *expected = [[NSDate alloc] initWithTimeInterval:-1000 sinceDate:now];
    action.finishTime = now;
    
    STAssertTrue([action.maxStartTime compare:expected] == NSOrderedSame, @"Setting a timeCalc should change the startTime");
    
    container.amount = 10;
    expected = [[NSDate alloc] initWithTimeInterval:-1*10*10 sinceDate:now];
    STAssertTrue([action.maxStartTime compare:expected] == NSOrderedSame, @"swapping units should still yield the correct startTime");
}


@end
