//
//  XTTableColumnWidthTracker.m
//  XTads
//
//  Created by Rune Berg on 07/09/2018.
//  Copyright © 2018 Rune Berg. All rights reserved.
//

#import "XTTableDimensionsTracker.h"
#import "XTTableInfo.h"
#import "XTTableColumnInfo.h"
#import "XTTextTable.h"
#import "XTTextTableBlock.h"
#import "XTLogger.h"
#import "XTAllocDeallocCounter.h"


@interface XTTableDimensionsTracker ()

@property NSUInteger nextTableId;
@property NSMutableDictionary<NSNumber*, XTTableInfo*> *tableInfoByTableId;

@end

@implementation XTTableDimensionsTracker

static XTLogger *logger;
static XTTableDimensionsTracker *singletonInstance = nil;

#define VOID_HANDLE_MISSING_TABLE_INFO(tableInfo) \
    if (tableInfo == nil) { \
       /* This shouldn't happen, but just in case: */ \
       XT_DEF_SELNAME; \
       XT_ERROR_1(@"tableInfo == nil for tableId %@", tableId); \
	}
#define HANDLE_MISSING_TABLE_INFO(tableInfo) \
	if (tableInfo == nil) { \
		/* This shouldn't happen, but just in case: */ \
		XT_DEF_SELNAME; \
		XT_ERROR_1(@"tableInfo == nil for tableId %@", tableId); \
		return 10.0; /* gotta return something :-( */ \
	}

+ (void)initialize
{
	logger = [XTLogger loggerForClass:[XTTableDimensionsTracker class]];
	if (singletonInstance == nil) {
		singletonInstance = [XTTableDimensionsTracker new];
	}
}

+ (id)tracker
{
	return singletonInstance;
}

OVERRIDE_ALLOC_FOR_COUNTER
OVERRIDE_DEALLOC_FOR_COUNTER

- (instancetype)init
{
	self = [super init];
	if (self) {
		_nextTableId = 1;
		_tableInfoByTableId = [NSMutableDictionary<NSNumber*, XTTableInfo*> dictionary];
	}
	return self;
}

- (NSNumber *)registerNewTable
{
	NSNumber *tableId = [NSNumber numberWithUnsignedInteger:self.nextTableId];
	self.nextTableId += 1;
	
	self.tableInfoByTableId[tableId] = [XTTableInfo new];
	
	return tableId;
}

- (void)noteMaxContentRectWidthForTable:(NSNumber *)tableId
						 textTableBlock:(XTTextTableBlock *)textTableBlock
								  width:(CGFloat)width
{
	XTTableInfo *tableInfo = self.tableInfoByTableId[tableId];
	VOID_HANDLE_MISSING_TABLE_INFO(tableInfo);
	
	CGFloat widthUsed;
	if (textTableBlock.widthAsPoints != nil) {
		widthUsed = textTableBlock.widthAsPoints.unsignedIntegerValue;
	} else {
		widthUsed = width;
	}

	[tableInfo noteMaxContentRectWidth:widthUsed forColumn:textTableBlock.startingColumn];
}

- (void)noteMinContentRectWidthForTable:(NSNumber *)tableId
						 textTableBlock:(XTTextTableBlock *)textTableBlock
								  width:(CGFloat)width
{
	XTTableInfo *tableInfo = self.tableInfoByTableId[tableId];
	VOID_HANDLE_MISSING_TABLE_INFO(tableInfo);

	[tableInfo noteMinContentRectWidth:width
							 forColumn:textTableBlock.startingColumn
								forRow:textTableBlock.startingRow];
}


- (CGFloat)minContentRectWidthForTable:(NSNumber *)tableId
						textTableBlock:(XTTextTableBlock *)textTableBlock
{
	XTTableInfo *tableInfo = self.tableInfoByTableId[tableId];
	VOID_HANDLE_MISSING_TABLE_INFO(tableInfo);

	CGFloat res = [tableInfo minContentRectWidthForColumn:textTableBlock.startingColumn];
	return res;
}

- (void)noteMinContentRectHeightForTable:(NSNumber *)tableId
						  textTableBlock:(XTTextTableBlock *)textTableBlock
								   height:(CGFloat)height
{
	XTTableInfo *tableInfo = self.tableInfoByTableId[tableId];
	VOID_HANDLE_MISSING_TABLE_INFO(tableInfo);

	[tableInfo noteMinContentRectHeight:height forRow:textTableBlock.startingRow];
}

- (CGFloat)contentRectWidthForTable:(NSNumber *)tableId
					 textTableBlock:(XTTextTableBlock *)textTableBlock
						usableWidth:(CGFloat)usableWidth
{
	XTTableInfo *tableInfo = self.tableInfoByTableId[tableId];
	HANDLE_MISSING_TABLE_INFO(tableInfo);
	
	CGFloat contentRectWidth = [tableInfo contectRectWidthForTextTableBlock:textTableBlock usableWidth:usableWidth];
	return contentRectWidth;
}

- (CGFloat)contentRectHeightForTable:(NSNumber *)tableId
					  textTableBlock:(XTTextTableBlock *)textTableBlock
					   visibleHeight:(CGFloat)visibleHeight
{
	XTTableInfo *tableInfo = self.tableInfoByTableId[tableId];
	HANDLE_MISSING_TABLE_INFO(tableInfo);
	
	CGFloat contentRectHeight = [tableInfo contectRectHeightForTextTableBlock:textTableBlock visibleHeight:visibleHeight];
	return contentRectHeight;
}

- (void)noteTotalBoundsForTable:(NSNumber *)tableId
				 textTableBlock:(XTTextTableBlock *)textTableBlock
						  width:(CGFloat)width
						 height:(CGFloat)height
{
	XTTableInfo *tableInfo = self.tableInfoByTableId[tableId];
	VOID_HANDLE_MISSING_TABLE_INFO(tableInfo);
	
	[tableInfo noteTotalBoundsForTextTableBlock:textTableBlock
										  width:width
										 height:height];
}

- (void)noteBoundsRectForTable:(NSNumber *)tableId
				textTableBlock:(XTTextTableBlock *)textTableBlock
						 width:(CGFloat)width
						height:(CGFloat)height
{
	XTTableInfo *tableInfo = self.tableInfoByTableId[tableId];
	VOID_HANDLE_MISSING_TABLE_INFO(tableInfo);
	
	[tableInfo noteBoundsRectForTextTableBlock:textTableBlock
										 width:width
										height:height];
}

- (void)noteHorizRulerWidthAsPoints:(NSNumber *)tableId
					 textTableBlock:(XTTextTableBlock *)textTableBlock
							  width:(CGFloat)width
{
	XTTableInfo *tableInfo = self.tableInfoByTableId[tableId];
	VOID_HANDLE_MISSING_TABLE_INFO(tableInfo);

	[tableInfo noteHorizRulerWidthAsPoints:width
								 forColumn:textTableBlock.startingColumn];
}

- (CGFloat)contentRectXForTable:(NSNumber *)tableId
				 textTableBlock:(XTTextTableBlock *)textTableBlock
						originX:(CGFloat)originX
					usableWidth:(CGFloat)usableWidth

{
	XTTableInfo *tableInfo = self.tableInfoByTableId[tableId];
	HANDLE_MISSING_TABLE_INFO(tableInfo);
	
	CGFloat contentRectX = [tableInfo contentRectXForTextTableBlock:textTableBlock
															originX:originX
														usableWidth:usableWidth];
	return contentRectX;
}


- (CGFloat)totalTableWidth:(NSNumber *)tableId
{
	XTTableInfo *tableInfo = self.tableInfoByTableId[tableId];
	HANDLE_MISSING_TABLE_INFO(tableInfo);

	CGFloat res = [tableInfo totalTableWidth];
	return res;
}

- (void)clearAll
{
	for (XTTableInfo *tableInfo in self.tableInfoByTableId.allValues) {
		[tableInfo clear];
	}
	[self.tableInfoByTableId removeAllObjects];
}

- (void)clearForRecalcOfTables
{
	for (XTTableInfo *tableInfo in self.tableInfoByTableId.allValues) {
		[tableInfo clearForRecalcOfTables];
	}
}

@end
