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

#import "MealTests.h"
#import "Meal.h"
#import "Measurements.h"


@implementation MealTests

-(Recipe *)buildRecipe1{
    RecipeAction *action1 = [[RecipeAction alloc] initWithAction:@"Do a thing" withTime:137];
    RecipeAction *action2 = [[RecipeAction alloc] initWithAction:@"Do another thing" withTime:234135];
    RecipeAction *action3 = [[RecipeAction alloc] initWithAction:@"Do something else with the first thing" withTime:9920];
    action1.nextAction = action3;
    
    Recipe *recipe = [[Recipe alloc] init];
    [recipe addAction:action1];
    [recipe addAction:action2];
    [recipe addAction:action3];
    
    Ingredient *ingredient1 = [[Ingredient alloc] initWithName:@"ing1" andAmount:[[Gram alloc] initWithAmount:25]];
    Ingredient *ingredient2 = [[Ingredient alloc] initWithName:@"ing2" andAmount:[[Gram alloc] initWithAmount:70]];
    
    [recipe addIngredient:ingredient1];
    [recipe addIngredient:ingredient2];
    
    return recipe;
}

-(Recipe *)buildRecipe2{
    RecipeAction *action1 = [[RecipeAction alloc] initWithAction:@"Do a thing" withTime:2000];
    RecipeAction *action2 = [[RecipeAction alloc] initWithAction:@"Do another thing" withTime:6];
    RecipeAction *action3 = [[RecipeAction alloc] initWithAction:@"Do something else with the first thing" withTime:277];
    action1.nextAction = action3;
    RecipeAction *action4 = [[RecipeAction alloc] initWithAction:@"Do something different than the other stuff you just did" withTime:6];
    action1.nextAction = action4;
    
    Recipe *recipe = [[Recipe alloc] init];
    [recipe addAction:action1];
    [recipe addAction:action2];
    [recipe addAction:action3];
    [recipe addAction:action4];
    
    return recipe;
}

-(void)testEmptyMealDirectionsReturnsNil{
    Meal* testMeal = [[Meal alloc] init];
    STAssertNil([testMeal getOrderedDirections], @"A meal with no recipes should return nil");
}

-(void)testFinishTimeSetsRecipesFinishTime{
    Meal* testMeal = [[Meal alloc] init];
    [testMeal addRecipe:[self buildRecipe1]];
    NSDate *finishTime = [NSDate date];
    testMeal.finishTime = finishTime;
    NSArray *recipes = [testMeal getRecipes];
    
    STAssertTrue([finishTime isEqualToDate:testMeal.finishTime], @"Setting finishTime should actually set finishTime");
    STAssertTrue([testMeal.finishTime isEqualToDate:((RecipeScaler *)recipes[0]).recipe.finishTime], @"Setting FinishTime after adding recipes should change recipes added");
    
    [testMeal addRecipe:[self buildRecipe2]];
    recipes = [testMeal getRecipes];
    STAssertTrue([testMeal.finishTime isEqualToDate:((RecipeScaler *)recipes[1]).recipe.finishTime], @"Adding a recipe after setting a time should set the new recipe's time");
}

-(void)testMealDirectionsAreOrdered{
    Meal *testMeal = [[Meal alloc] init];
    Recipe *recipe1 = [self buildRecipe1];
    Recipe *recipe2 = [self buildRecipe2];
    [testMeal addRecipe:recipe1];
    [testMeal addRecipe:recipe2];
    testMeal.finishTime = [NSDate date];
    
    NSArray *orderedRecipes = [testMeal getOrderedDirections];
    STAssertNotNil(orderedRecipes, @"getOrderedDirections should not return a nil collection");
    STAssertFalse([orderedRecipes count] == 0, @"A meal with recipes should not return an empty orderedDirections collection");
    
    for (int i = 0; i < [orderedRecipes count]-1; ++i){
        RecipeAction *thisAction = (RecipeAction *)orderedRecipes[i];
        RecipeAction *nextAction = (RecipeAction *)orderedRecipes[i+1];
        STAssertTrue([thisAction compare:nextAction] != NSOrderedDescending, @"Start times are not ordered correcly");
    }
}

-(void)testMealDirectionsCombineLikeDirections{
    Meal *testMeal = [[Meal alloc] init];
    Recipe *recipe1 = [self buildRecipe1];
    Recipe *recipe2 = [recipe1 copy];
    [testMeal addRecipe:recipe1];
    [testMeal addRecipe:recipe2];
    
    NSArray* orderedDirections = [testMeal getOrderedDirections];
    STAssertTrue([[recipe1 getDirections] isEqualToArray:orderedDirections], @"Recipes with similar directions should combine directions");
}

-(void)testGetShoppingListReturnsArray{
    Meal *testMeal = [[Meal alloc] init];
    NSArray *shoppingList = [testMeal getShoppingList];
    STAssertNotNil(shoppingList, @"getShoppingList should return an array");
}

-(void)testShoppingListCombinesIngredients{
    Meal *meal = [[Meal alloc] init];
    [meal addRecipe:[self buildRecipe1]];
    Recipe* recipe2 = [self buildRecipe1];
    float amount1 = ((Ingredient *)[recipe2 getIngredients][0]).amount.amount;
    [meal addRecipe:recipe2];
    NSArray *shoppingList = [meal getShoppingList];
    STAssertEquals(2U, [shoppingList count], @"duplicate ingredients should be combined");
    STAssertEqualsWithAccuracy(amount1*2, ((Ingredient *)shoppingList[0]).amount.amount, 0.1, @"duplicate ingredients should be combined accurately");
}

@end
