//
//  XTTabStopModelTests.m
//  XTads
//
//  Created by Rune Berg on 08/02/2017.
//  Copyright © 2017 Rune Berg. All rights reserved.
//

#import <XCTest/XCTest.h>
#import "XTTabStopModel.h"
#import "XTTabStopModelEntry.h"


@interface XTTabStopModelTests : XCTestCase

@property XTTabStopModel *model; // the object being tested

@end


@implementation XTTabStopModelTests

#define ALIGN_LEFT @"left"
#define ALIGN_CENTER @"center"
#define ALIGN_RIGHT @"right"
#define ALIGN_DECPT @"decimal"

- (void)setUp
{
    [super setUp];
	self.model = [XTTabStopModel new];
}

- (void)tearDown
{
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}

- (void)test_initialState
{
	XCTAssertEqual(0, self.model.count);
}

- (void)test_addTabStopWithId_basic1
{
	XTTabStopModelEntry *entry;
	
	XCTAssertEqual(0, self.model.count);

	[self.model addTabStopWithId:@"id1" position:1.0 alignment:ALIGN_LEFT decimalChar:@"."];
	XCTAssertEqual(1, self.model.count);
	entry = [self.model	entryAtIndex:0];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id1", entry.ident);
	XCTAssertEqual(1.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_LEFT, entry.alignment.integerValue);
	XCTAssertEqualObjects(@".", entry.decimalChar);
}

- (void)test_addTabStopWithId_basic2
{
	XTTabStopModelEntry *entry;
	
	[self.model addTabStopWithId:@"idX" position:2.2 alignment:ALIGN_CENTER  decimalChar:@";"];
	XCTAssertEqual(1, self.model.count);
	entry = [self.model	entryAtIndex:0];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"idX", entry.ident);
	XCTAssertEqual(2.2, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_CENTER, entry.alignment.integerValue);
	XCTAssertEqualObjects(@";", entry.decimalChar);
}

- (void)test_addTabStopWithId_basic3
{
	XTTabStopModelEntry *entry;
	
	[self.model addTabStopWithId:@"id1" position:0.01 alignment:ALIGN_RIGHT decimalChar:nil];
	XCTAssertEqual(1, self.model.count);
	entry = [self.model	entryAtIndex:0];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id1", entry.ident);
	XCTAssertEqual(0.01, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_RIGHT, entry.alignment.integerValue);
	XCTAssertNil(entry.decimalChar);
}

- (void)test_addTabStopWithId_basic4
{
	XTTabStopModelEntry *entry;
	
	[self.model addTabStopWithId:@"id1" position:7.0 alignment:ALIGN_DECPT decimalChar:nil];
	XCTAssertEqual(1, self.model.count);
	entry = [self.model	entryAtIndex:0];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id1", entry.ident);
	XCTAssertEqual(7.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_DEC_POINT, entry.alignment.integerValue);
	XCTAssertNil(entry.decimalChar);
}

- (void)test_addTabStopWithId_basic5
{
	XTTabStopModelEntry *entry;
	
	[self.model addTabStopWithId:@"id1" position:8.0 alignment:nil decimalChar:nil];
	XCTAssertEqual(1, self.model.count);
	entry = [self.model	entryAtIndex:0];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id1", entry.ident);
	XCTAssertEqual(8.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_LEFT, entry.alignment.integerValue);
	XCTAssertNil(entry.decimalChar);
}

- (void)test_addTabStopWithId_severalEntries
{
	XTTabStopModelEntry *entry;
	
	[self.model addTabStopWithId:@"id1" position:1.0 alignment:ALIGN_LEFT decimalChar:@"?"];
	[self.model addTabStopWithId:@"id2" position:2.0 alignment:ALIGN_RIGHT decimalChar:nil];
	[self.model addTabStopWithId:@"id3" position:3.0 alignment:ALIGN_CENTER decimalChar:@"-"];
	XCTAssertEqual(3, self.model.count);

	entry = [self.model	entryAtIndex:0];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id1", entry.ident);
	XCTAssertEqual(1.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_LEFT, entry.alignment.integerValue);
	XCTAssertEqualObjects(@"?", entry.decimalChar);
	
	entry = [self.model	entryAtIndex:1];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id2", entry.ident);
	XCTAssertEqual(2.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_RIGHT, entry.alignment.integerValue);
	XCTAssertNil(entry.decimalChar);
	
	entry = [self.model	entryAtIndex:2];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id3", entry.ident);
	XCTAssertEqual(3.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_CENTER, entry.alignment.integerValue);
	XCTAssertEqualObjects(@"-", entry.decimalChar);
}

- (void)test_addTabStopWithId_ordering1
{
	XTTabStopModelEntry *entry;
	
	[self.model addTabStopWithId:@"id2" position:2.0 alignment:ALIGN_RIGHT decimalChar:nil];
	[self.model addTabStopWithId:@"id1" position:1.0 alignment:ALIGN_LEFT decimalChar:nil];
	XCTAssertEqual(2, self.model.count);
	
	entry = [self.model	entryAtIndex:0];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id1", entry.ident);
	XCTAssertEqual(1.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_LEFT, entry.alignment.integerValue);

	entry = [self.model	entryAtIndex:1];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id2", entry.ident);
	XCTAssertEqual(2.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_RIGHT, entry.alignment.integerValue);
}

- (void)test_addTabStopWithId_ordering2
{
	XTTabStopModelEntry *entry;
	
	[self.model addTabStopWithId:@"id3" position:3.0 alignment:ALIGN_CENTER decimalChar:nil];
	[self.model addTabStopWithId:@"id1" position:1.0 alignment:ALIGN_LEFT decimalChar:nil];
	[self.model addTabStopWithId:@"id4" position:4.0 alignment:ALIGN_DECPT decimalChar:nil];
	[self.model addTabStopWithId:@"id2" position:2.0 alignment:ALIGN_RIGHT decimalChar:nil];
	XCTAssertEqual(4, self.model.count);
	
	entry = [self.model	entryAtIndex:0];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id1", entry.ident);
	XCTAssertEqual(1.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_LEFT, entry.alignment.integerValue);
	
	entry = [self.model	entryAtIndex:1];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id2", entry.ident);
	XCTAssertEqual(2.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_RIGHT, entry.alignment.integerValue);
	
	entry = [self.model	entryAtIndex:2];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id3", entry.ident);
	XCTAssertEqual(3.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_CENTER, entry.alignment.integerValue);
	
	entry = [self.model	entryAtIndex:3];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id4", entry.ident);
	XCTAssertEqual(4.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_DEC_POINT, entry.alignment.integerValue);
}

- (void)test_addTabStopWithId_ordering3
{
	XTTabStopModelEntry *entry;
	
	[self.model addTabStopWithId:@"id1" position:1.0 alignment:ALIGN_LEFT decimalChar:nil];
	[self.model addTabStopWithId:@"id2" position:1.0 alignment:ALIGN_RIGHT decimalChar:nil];
	[self.model addTabStopWithId:@"id3" position:1.0 alignment:ALIGN_CENTER decimalChar:nil];
	XCTAssertEqual(3, self.model.count);
	
	entry = [self.model	entryAtIndex:0];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id1", entry.ident);
	XCTAssertEqual(1.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_LEFT, entry.alignment.integerValue);
	
	entry = [self.model	entryAtIndex:1];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id2", entry.ident);
	XCTAssertEqual(1.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_RIGHT, entry.alignment.integerValue);
	
	entry = [self.model	entryAtIndex:2];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id3", entry.ident);
	XCTAssertEqual(1.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_CENTER, entry.alignment.integerValue);
}

- (void)test_addTabStopWithId_ordering4
{
	XTTabStopModelEntry *entry;
	
	[self.model addTabStopWithId:@"id2" position:1.0 alignment:ALIGN_RIGHT decimalChar:nil];
	[self.model addTabStopWithId:@"id4" position:4.0 alignment:ALIGN_DECPT decimalChar:nil];
	[self.model addTabStopWithId:@"id1" position:1.0 alignment:ALIGN_LEFT decimalChar:nil];
	[self.model addTabStopWithId:@"id3" position:0.9 alignment:ALIGN_CENTER decimalChar:nil];
	XCTAssertEqual(4, self.model.count);
	
	entry = [self.model	entryAtIndex:0];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id3", entry.ident);
	XCTAssertEqual(0.9, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_CENTER, entry.alignment.integerValue);
	
	entry = [self.model	entryAtIndex:1];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id2", entry.ident);
	XCTAssertEqual(1.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_RIGHT, entry.alignment.integerValue);
	
	entry = [self.model	entryAtIndex:2];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id1", entry.ident);
	XCTAssertEqual(1.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_LEFT, entry.alignment.integerValue);
	
	entry = [self.model	entryAtIndex:3];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id4", entry.ident);
	XCTAssertEqual(4.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_DEC_POINT, entry.alignment.integerValue);
}

- (void)test_addTabStopWithId_replaceExisting_1
{
	XTTabStopModelEntry *entry;
	
	[self.model addTabStopWithId:@"id1" position:1.0 alignment:ALIGN_LEFT decimalChar:nil];
	[self.model addTabStopWithId:@"id2" position:2.0 alignment:ALIGN_RIGHT decimalChar:nil];
	[self.model addTabStopWithId:@"id3" position:3.0 alignment:ALIGN_CENTER decimalChar:nil];
	XCTAssertEqual(3, self.model.count);

	[self.model addTabStopWithId:@"id2" position:0.1 alignment:ALIGN_LEFT decimalChar:nil];
	XCTAssertEqual(3, self.model.count);
	
	entry = [self.model	entryAtIndex:0];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id2", entry.ident);
	XCTAssertEqual(0.1, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_LEFT, entry.alignment.integerValue);
	XCTAssertNil(entry.decimalChar);

	entry = [self.model	entryAtIndex:1];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id1", entry.ident);
	XCTAssertEqual(1.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_LEFT, entry.alignment.integerValue);
	XCTAssertNil(entry.decimalChar);
	
	entry = [self.model	entryAtIndex:2];
	XCTAssertNotNil(entry);
	XCTAssertEqualObjects(@"id3", entry.ident);
	XCTAssertEqual(3.0, entry.position.doubleValue);
	XCTAssertEqual(XTTABSTOP_ALIGN_CENTER, entry.alignment.integerValue);
	XCTAssertNil(entry.decimalChar);

	//TODO ... variations on this test
}

//-------

- (void)test_findTabWithId_1
{
	[self.model addTabStopWithId:@"id1" position:1.0 alignment:ALIGN_LEFT decimalChar:nil];
	[self.model addTabStopWithId:@"id2" position:2.0 alignment:ALIGN_LEFT decimalChar:nil];
	[self.model addTabStopWithId:@"id3" position:3.0 alignment:ALIGN_LEFT decimalChar:nil];
	
	XTTabStopModelEntry *foundTabStop;

	foundTabStop = [self.model findTabWithId:@"id1"];
	XCTAssertEqualObjects(@"id1", foundTabStop.ident);
	
	foundTabStop = [self.model findTabWithId:@"id2"];
	XCTAssertEqualObjects(@"id2", foundTabStop.ident);

	foundTabStop = [self.model findTabWithId:@"id3"];
	XCTAssertEqualObjects(@"id3", foundTabStop.ident);
}

- (void)test_findNumberOfTabsToId_2
{
	[self.model addTabStopWithId:@"id1" position:1.0 alignment:ALIGN_LEFT decimalChar:nil];

	XTTabStopModelEntry *foundTabStop;
	
	foundTabStop = [self.model findTabWithId:@"id1"];
	XCTAssertEqualObjects(@"id1", foundTabStop.ident);
}

- (void)test_findNumberOfTabsToId_3
{
	// find unknown tabs
	
	XTTabStopModelEntry *foundTabStop;
	
	foundTabStop = [self.model findTabWithId:@"id1"];
	XCTAssertNil(foundTabStop);
}

- (void)test_findNumberOfTabsToId_4
{
	// find unknown tabs

	[self.model addTabStopWithId:@"id1" position:1.0 alignment:ALIGN_LEFT decimalChar:nil];
	[self.model addTabStopWithId:@"id2" position:2.0 alignment:ALIGN_LEFT decimalChar:nil];
	[self.model addTabStopWithId:@"id3" position:3.0 alignment:ALIGN_LEFT decimalChar:nil];
	
	XTTabStopModelEntry *foundTabStop;
	
	foundTabStop = [self.model findTabWithId:@"id99"];
	XCTAssertNil(foundTabStop);
}

- (void)test_findNumberOfTabsToId_5
{
	// case insensitivity of to attr value
	
	[self.model addTabStopWithId:@"id1" position:1.0 alignment:ALIGN_LEFT decimalChar:nil];
	[self.model addTabStopWithId:@"id2" position:2.0 alignment:ALIGN_LEFT decimalChar:nil];
	
	XTTabStopModelEntry *foundTabStop;
	CGFloat enSpaceWidth = 100.0; // so it doesn't affect yhis test
	
	foundTabStop = [self.model findTabWithId:@"id1"];
	XCTAssertEqualObjects(@"id1", foundTabStop.ident);
	foundTabStop = [self.model findTabWithId:@"ID1"];
	XCTAssertEqualObjects(@"id1", foundTabStop.ident);
	
	foundTabStop = [self.model findTabWithId:@"id2"];
	XCTAssertEqualObjects(@"id2", foundTabStop.ident);
	foundTabStop = [self.model findTabWithId:@"iD2"];
	XCTAssertEqualObjects(@"id2", foundTabStop.ident);
}

@end
