//
//  XTRecentGameFilesTests.m
//  XTads
//
//  Created by Rune Berg on 07/08/15.
//  Copyright (c) 2015 Rune Berg. All rights reserved.
//

#import <Cocoa/Cocoa.h>
#import <XCTest/XCTest.h>
#import "XTRecentGameFiles.h"


@interface XTRecentGameFilesTests : XCTestCase

@property XTRecentGameFiles *recentGameFiles;
@property XTRecentGameFilesEntry *entry1;
@property XTRecentGameFilesEntry *entry2;
@property XTRecentGameFilesEntry *entry3;
@property XTRecentGameFilesEntry *entry4;
@property XTRecentGameFilesEntry *entry5;

@end


@implementation XTRecentGameFilesTests

- (void)setUp
{
    [super setUp];
	self.recentGameFiles = [XTRecentGameFiles new];
	self.entry1 = [XTRecentGameFilesEntry entryWithGameFileUrl:[NSURL URLWithString:@"file:///game1.gam"] gameTitle:@"title1"];
	self.entry2 = [XTRecentGameFilesEntry entryWithGameFileUrl:[NSURL URLWithString:@"file:///game2.gam"] gameTitle:@"title2"];
	self.entry3 = [XTRecentGameFilesEntry entryWithGameFileUrl:[NSURL URLWithString:@"file:///game3.gam"] gameTitle:@"title3"];
	self.entry4 = [XTRecentGameFilesEntry entryWithGameFileUrl:[NSURL URLWithString:@"file:///game4.gam"] gameTitle:@"title4"];
	self.entry5 = [XTRecentGameFilesEntry entryWithGameFileUrl:[NSURL URLWithString:@"file:///game5.gam"] gameTitle:@"title5"];
}

- (void)test_createEntry
{
	NSURL *url = [NSURL URLWithString:@"file:///game.gam"];
	NSString *title = @"title";
	XTRecentGameFilesEntry *entry = [XTRecentGameFilesEntry entryWithGameFileUrl:url gameTitle:title];
	XCTAssertEqualObjects(url, entry.gameFileUrl);
	XCTAssertEqualObjects(title, entry.gameTitle);
	
	entry = [XTRecentGameFilesEntry entryWithGameFileUrl:url gameTitle:nil];
	XCTAssertEqualObjects(url, entry.gameFileUrl);
	XCTAssertEqualObjects(@"game.gam", entry.gameTitle);
}

- (void)test_new
{
    XCTAssertEqual(10, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(0, self.recentGameFiles.numberOfEntries);
}

- (void)test_maxNumberOfEntries_basic
{
	self.recentGameFiles.maxNumberOfEntries = 3;
	XCTAssertEqual(3, self.recentGameFiles.maxNumberOfEntries);

	self.recentGameFiles.maxNumberOfEntries = 1;
	XCTAssertEqual(1, self.recentGameFiles.maxNumberOfEntries);

	self.recentGameFiles.maxNumberOfEntries = 0;
	XCTAssertEqual(0, self.recentGameFiles.maxNumberOfEntries);
}

- (void)test_maxNumberOfEntries_pruning_1
{
	self.recentGameFiles.maxNumberOfEntries = 10;
	XCTAssertEqual(10, self.recentGameFiles.maxNumberOfEntries);
	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	[self.recentGameFiles addNewestEntry:self.entry3];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry1];

	self.recentGameFiles.maxNumberOfEntries = 5;
	XCTAssertEqual(5, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry1];
	
	self.recentGameFiles.maxNumberOfEntries = 3;
	XCTAssertEqual(3, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry1];
	
	self.recentGameFiles.maxNumberOfEntries = 2;
	XCTAssertEqual(2, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(2, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry2];
	
	self.recentGameFiles.maxNumberOfEntries = 1;
	XCTAssertEqual(1, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(1, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	
	self.recentGameFiles.maxNumberOfEntries = 0;
	XCTAssertEqual(0, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(0, self.recentGameFiles.numberOfEntries);
}

- (void)test_maxNumberOfEntries_pruning_2
{
	self.recentGameFiles.maxNumberOfEntries = 10;
	XCTAssertEqual(10, self.recentGameFiles.maxNumberOfEntries);
	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	[self.recentGameFiles addNewestEntry:self.entry3];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry1];

	self.recentGameFiles.maxNumberOfEntries = 1;
	XCTAssertEqual(1, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(1, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	
	self.recentGameFiles.maxNumberOfEntries = 7;
	XCTAssertEqual(7, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(1, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
}

- (void)test_maxNumberOfEntries_pruning_3
{
	self.recentGameFiles.maxNumberOfEntries = 10;
	XCTAssertEqual(10, self.recentGameFiles.maxNumberOfEntries);
	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	[self.recentGameFiles addNewestEntry:self.entry3];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry1];
	
	self.recentGameFiles.maxNumberOfEntries = 0;
	XCTAssertEqual(0, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(0, self.recentGameFiles.numberOfEntries);
	
	self.recentGameFiles.maxNumberOfEntries = 5;
	XCTAssertEqual(5, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(0, self.recentGameFiles.numberOfEntries);
}

- (void)test_singleton
{
	XTRecentGameFiles *singleton1 = [XTRecentGameFiles recentGameFiles];
	XCTAssertNotNil(singleton1);
	
	XTRecentGameFiles *singleton2 = [XTRecentGameFiles recentGameFiles];
	XCTAssertNotNil(singleton2);
	XCTAssert(singleton1 == singleton2);
}

- (void)test_addEntry_basic
{
	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(10, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(1, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry1];

	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(10, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(2, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry2];  // newest first, remember?
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry1];
	
	[self.recentGameFiles addNewestEntry:self.entry3];
	XCTAssertEqual(10, self.recentGameFiles.maxNumberOfEntries);
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry1];
}

- (void)test_addEntry_excess
{
	self.recentGameFiles.maxNumberOfEntries = 3;
	
	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(1, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry1];
	
	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(2, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry1];
	
	[self.recentGameFiles addNewestEntry:self.entry3];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry1];

	[self.recentGameFiles addNewestEntry:self.entry4];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry4];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry2];
	
	[self.recentGameFiles addNewestEntry:self.entry5];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry5];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry4];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry3];
	
	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry1];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry5];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry4];
	
	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry1];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry5];
}

- (void)test_addEntry_duplicates_1of1
{
	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(1, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry1];
	
	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(1, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry1];
	
	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(1, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry1];
}

- (void)test_addEntry_duplicates_1of2
{
	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(2, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry1];
	
	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(2, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry1];
}

- (void)test_addEntry_duplicates_2of2
{
	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(2, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry1];

	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(2, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry1];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry2];
	
	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(2, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry1];
}

- (void)test_addEntry_duplicates_2of3
{
	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	[self.recentGameFiles addNewestEntry:self.entry3];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry1];

	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry1];
}
	
- (void)test_addEntry_duplicates_3of3
{
	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	[self.recentGameFiles addNewestEntry:self.entry3];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry2];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry1];
	
	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry1];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry2];
	
	// and again...
	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry1];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry3];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry2];
}

- (void)test_addEntry_shortenMax_to3
{
	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	[self.recentGameFiles addNewestEntry:self.entry3];
	[self.recentGameFiles addNewestEntry:self.entry4];
	[self.recentGameFiles addNewestEntry:self.entry5];
	XCTAssertEqual(5, self.recentGameFiles.numberOfEntries);

	self.recentGameFiles.maxNumberOfEntries = 3;
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry5];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry4];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry3];

	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry1];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry5];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry4];
}

- (void)test_addEntry_shortenMax_to1
{
	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	[self.recentGameFiles addNewestEntry:self.entry3];
	[self.recentGameFiles addNewestEntry:self.entry4];
	[self.recentGameFiles addNewestEntry:self.entry5];
	XCTAssertEqual(5, self.recentGameFiles.numberOfEntries);
	
	self.recentGameFiles.maxNumberOfEntries = 1;
	XCTAssertEqual(1, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry5];

	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(1, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry2];
}

- (void)test_addEntry_shortenMax_to0
{
	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(2, self.recentGameFiles.numberOfEntries);
	
	self.recentGameFiles.maxNumberOfEntries = 0;
	XCTAssertEqual(0, self.recentGameFiles.numberOfEntries);

	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(0, self.recentGameFiles.numberOfEntries);
}

- (void)test_addEntry_lengthenMax
{
	self.recentGameFiles.maxNumberOfEntries = 2;
	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	XCTAssertEqual(2, self.recentGameFiles.numberOfEntries);

	[self.recentGameFiles addNewestEntry:self.entry3];
	[self.recentGameFiles addNewestEntry:self.entry4];
	XCTAssertEqual(2, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry4];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry3];

	self.recentGameFiles.maxNumberOfEntries = 3;
	XCTAssertEqual(3, self.recentGameFiles.maxNumberOfEntries);
	[self.recentGameFiles addNewestEntry:self.entry5];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry5];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry4];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry3];
	
	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self checkThatEntryAtIndex:0 isEqualTo:self.entry1];
	[self checkThatEntryAtIndex:1 isEqualTo:self.entry5];
	[self checkThatEntryAtIndex:2 isEqualTo:self.entry4];
}

- (void)test_removeAllEntries
{
	XCTAssertEqual(0, self.recentGameFiles.numberOfEntries);
	
	[self.recentGameFiles removeAllEntries];
	XCTAssertEqual(0, self.recentGameFiles.numberOfEntries);

	[self.recentGameFiles removeAllEntries];
	[self.recentGameFiles removeAllEntries];
	[self.recentGameFiles removeAllEntries];
	XCTAssertEqual(0, self.recentGameFiles.numberOfEntries);

	[self.recentGameFiles addNewestEntry:self.entry1];
	XCTAssertEqual(1, self.recentGameFiles.numberOfEntries);
	[self.recentGameFiles removeAllEntries];
	XCTAssertEqual(0, self.recentGameFiles.numberOfEntries);

	[self.recentGameFiles addNewestEntry:self.entry1];
	[self.recentGameFiles addNewestEntry:self.entry2];
	[self.recentGameFiles addNewestEntry:self.entry3];
	XCTAssertEqual(3, self.recentGameFiles.numberOfEntries);
	[self.recentGameFiles removeAllEntries];
	XCTAssertEqual(0, self.recentGameFiles.numberOfEntries);
}

//------------

- (void)checkThatEntryAtIndex:(NSUInteger)index isEqualTo:(XTRecentGameFilesEntry *)expectedEntry
{
	XTRecentGameFilesEntry *actualEntry = [self.recentGameFiles entryAtIndex:index];
	XCTAssertNotNil(actualEntry);
	XCTAssertEqualObjects(expectedEntry.gameFileUrl, actualEntry.gameFileUrl);
	XCTAssertEqualObjects(expectedEntry.gameTitle, actualEntry.gameTitle);
}

@end
