//
//  XTGameWindowController_vmThreadBannerApi.m
//  XTads
//
//  Created by Rune Berg on 15/12/15.
//  Copyright © 2015 Rune Berg. All rights reserved.
//
//  IMPORTANT NOTE: This is not a standalone .m file, and so should
//  *not* be member of any build targets. Instead, it's #included by
//  XTGameWindowController.m proper.
//

- (void *)bannerCreate:(void *)parent
				 where:(NSInteger)where
				 other:(void *)other
			   wintype:(NSInteger)wintype
				 align:(NSInteger)align
				  size:(NSInteger)size
			 sizeUnits:(NSInteger)sizeUnits
				 style:(NSUInteger)style
{
	XT_DEF_SELNAME;
	XT_TRACE_0(@"ENTER");

	RETURN_VALUE_IF_SHUTTING_DOWN_VM_THREAD(0);

	XTBannerCreateParams *params = [XTBannerCreateParams new];
	params.parent = parent;
	params.where = where;
	params.other = other;
	params.wintype = wintype;
	params.align = align;
	params.size = size;
	params.sizeUnits = sizeUnits;
	params.style = style;
	
	[self callOnMainThread:@selector(mainThread_bannerCreate:)
				withObject:params];

	return params.bannerHandle;
}

- (void)tagBannerReconfigure:(void *)handle
					   align:(NSUInteger)align
			  sizeToContents:(BOOL)sizeToContents
			  sizeAsPrevious:(BOOL)sizeAsPrevious
						size:(NSUInteger)size
				   sizeUnits:(NSUInteger)sizeUnits
					   style:(NSUInteger)style
{
	XT_DEF_SELNAME;
	//XT_WARN_1(@"handle=%lu", (NSUInteger)handle);
	
	XTBannerTextHandler *banner = [self getBanner:handle];
	
	BOOL wasSizedToContent = banner.isSizedToContent;
	
	banner.isSizedToContent = NO;
	banner.tagBannerNeedsSizeToContent = NO;
	banner.alignment = align;
	
	if (sizeAsPrevious) {
		//TODO this logic (and the state it uses) is probably much more complicated than it needs to be :-(
		
		if (banner.initialSize != nil) {
			if (banner.hadUnspecifiedSizeLastTime && banner.wasInitiallySizedToPrevious) {
				// Keep current size
				banner.isSizedToContent = YES;
				//XT_WARN_0(@"hadUnspecifiedSizeLastTime && wasInitiallySizedToPrevious --> no change");
				int brkpt = 1;
			} else if (banner.hadPreviousSizeLastTime && banner.wasInitiallySizedToPrevious) {
				// Keep current size
				banner.isSizedToContent = wasSizedToContent;
				//XT_WARN_0(@"hadPreviousSizeLastTime && wasInitiallySizedToPrevious --> no change");
				int brkpt = 1;
			} else {
				if (banner.wasInitiallySizedToPrevious) {
					// Keep current size
					int brkpt = 1;
				} else if (banner.wasInitiallySizedToContents) {
					banner.size = [banner.initialSize unsignedIntegerValue];
					banner.sizeOfContents = banner.initialSizeOfContents;
					//XT_WARN_1(@"self.sizeOfContents = %lf", banner.initialSizeOfContents);
					banner.isSizedToContent = YES;
					banner.sizeUnits = banner.initialSizeUnits;
				} else if (banner.initialSizeUnits == OS_BANNER_SIZE_ABS) {
					banner.size = (NSUInteger)[banner.initialSize doubleValue];
					banner.sizeUnits = banner.initialSizeUnits;
				} else {
					banner.size = [banner.initialSize unsignedIntegerValue];
					banner.sizeUnits = banner.initialSizeUnits;
				}
			}
		} else {
			XT_ERROR_0(@"sizeAsPrevious && banner.initialSize == nil");
		}
	} else if (sizeToContents) {
		//XT_WARN_0(@"tagBannerNeedsSizeToContent set to YES");
		banner.tagBannerNeedsSizeToContent = YES;
	} else {
		banner.size = size;
		banner.sizeUnits = sizeUnits;
	}
	
	banner.style = style;
}

- (void *)bannerHandleForTagId:(NSString *)tagId
{
	XT_DEF_SELNAME;
	
	void *handle = nil;
	
	if (tagId == nil || [tagId length] == 0) {
		XT_ERROR_0(@"tagId is nil or blank");
	} else {
		XTBannerTextHandler *banner = [self.bannersByTagId valueForKey:tagId];
		handle = (void *)banner.bannerIndex;
	}
	
	return handle;
}

- (XTBannerTextHandler *)bannerHandlerForHandle:(void *)handle
{
	XTBannerTextHandler *banner = [self getBanner:handle];
	return banner;
}

- (void)bannerDelete:(void *)banner_handle
{
	RETURN_IF_SHUTTING_DOWN_VM_THREAD;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner != nil) {
		[self callOnMainThread:@selector(mainThread_bannerDelete:)
					withObject:banner];
	}
}

- (void)bannerDeleteAll
{
	NSArray * allKeys = [self.bannersByHandle allKeys];
	for (NSNumber *handleObj in allKeys) {
		NSUInteger bannerIndex = handleObj.unsignedIntegerValue;
		if (bannerIndex >= 1) {
			void *bannerHandle = (void *)bannerIndex;
			XTBannerTextHandler *bannerTH = [self bannerHandlerForHandle:bannerHandle];
			if (! bannerTH.isForTradStatusLine) {
				[self bannerDelete:bannerHandle];
			}
		}
	}
}

- (void)bannerOrphan:(void *)banner_handle
{
	XT_DEF_SELNAME;
	XT_TRACE_1(@"%lu", (NSUInteger)banner_handle);

	// Do nothing - leave the screen as is
}

- (BOOL)bannerInfo:(void *)banner_handle info:(os_banner_info_t *)info
{
	BOOL res = NO;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner == nil) {
		return res;
	}
	
	res = YES;
	
	info->align = (int)banner.alignment;
	
	info->style = banner.style;
	info->style |= OS_BANNER_STYLE_TAB_ALIGN;  // because MJR's terp and QTads behave that way
	
	if (_shuttingDownTadsEventLoopThread) {
		return res;
	}
	NSArray *usableSizes = [self childThread_getUsableSizes:banner];

	NSNumber *usableHeightInRows = usableSizes[0];
	info->rows = usableHeightInRows.intValue;

	NSNumber *usableWidthInColumns = usableSizes[1];
	info->columns = usableWidthInColumns.intValue;

	NSNumber *usableHeightInPoints = usableSizes[2];
	info->pix_height = usableHeightInPoints.intValue;

	NSNumber *usableWidthInPoints = usableSizes[3];
	info->pix_width = usableWidthInPoints.intValue;
	
	info->os_line_wrap = 1;
	
	return res;
}

- (NSUInteger)bannerWidthInChars:(void *)banner_handle
{
	NSUInteger res = 0;

	if (_shuttingDownTadsEventLoopThread) {
		return res;
	}
	
	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner != nil) {
		if (banner.type & OS_BANNER_TYPE_TEXTGRID) {
			NSArray *usableSizes = [self childThread_getUsableSizes:banner];
			NSNumber *usableWidthInColumns = usableSizes[1];
			res = usableWidthInColumns.intValue;
		}
	}
	return res;
}

- (NSUInteger)bannerHeightInChars:(void *)banner_handle
{
	NSUInteger res = 0;
	
	if (_shuttingDownTadsEventLoopThread) {
		return res;
	}

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner != nil) {
		if (banner.type & OS_BANNER_TYPE_TEXTGRID) {
			NSArray *usableSizes = [self childThread_getUsableSizes:banner];
			NSNumber *usableHeightInRows = usableSizes[0];
			res = usableHeightInRows.intValue;
		}
	}
	
	return res;
}

- (NSArray *)childThread_getUsableSizes:(XTBannerTextHandler *)banner
{
	NSMutableArray *results = [NSMutableArray arrayWithCapacity:4];
	[banner callOnMainThread:@selector(mainThread_getUsableSizes:)
				  withObject:results];
	return results;
}

- (void)bannerDisplay:(void *)banner_handle text:(NSString *)string
{
	XT_DEF_SELNAME;
	XT_TRACE_1(@"\"%@\"", string);

	RETURN_IF_SHUTTING_DOWN_VM_THREAD;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner != nil) {
		[banner display:string];
	}
}

- (void)bannerSetTextColors:(void *)banner_handle
			foregroundColor:(os_color_t)fg
			backgroundColor:(os_color_t)bg
{
	RETURN_IF_SHUTTING_DOWN_VM_THREAD;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner != nil && [banner isGridMode]) {
		[banner callOnMainThread:@selector(mainThread_setForegroundColorForGrid:)
					withObject:[NSNumber numberWithUnsignedInteger:fg]];
		[banner callOnMainThread:@selector(mainThread_setBackgroundColorForGrid:)
					withObject:[NSNumber numberWithUnsignedInteger:bg]];
	}
}

- (void)bannerSetScreenColor:(void *)banner_handle
				 screenColor:(os_color_t)color
{
	RETURN_IF_SHUTTING_DOWN_VM_THREAD;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner != nil && [banner isGridMode]) {
		[banner callOnMainThread:@selector(mainThread_setScreenColorForGrid:)
					withObject:[NSNumber numberWithUnsignedInteger:color]];
	}
}

- (void)bannerDisplayTradStatusLineScoreString:(void *)banner_handle text:(NSString *)string
{
	RETURN_IF_SHUTTING_DOWN_VM_THREAD;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner != nil) {
		[banner displayTradStatusLineScoreString:string];
	}
}

- (void)bannerFlush:(void *)banner_handle
{
	RETURN_IF_SHUTTING_DOWN_VM_THREAD;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner != nil) {
		[self pumpOutputTextForHandler:banner flushIfBanner:TRUE];
	}
}

- (void)bannerSetHtmlMode:(void *)banner_handle on:(BOOL)on
{
	RETURN_IF_SHUTTING_DOWN_VM_THREAD;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	banner.htmlMode = on;
}

- (void)bannerClear:(void *)banner_handle
{
	XT_DEF_SELNAME;
	XT_TRACE_0(@"");

	RETURN_IF_SHUTTING_DOWN_VM_THREAD;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner != nil) {
		[banner callOnMainThread:@selector(mainThread_clear)];
	}
}

- (void)bannerSetSize:(void *)banner_handle
				 size:(NSUInteger)size
			sizeUnits:(NSUInteger)sizUnits
		   isAdvisory:(BOOL)isAdvisory
{
	RETURN_IF_SHUTTING_DOWN_VM_THREAD;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	
	if (banner != nil) {
		if (isAdvisory || ((size == banner.size) && (sizUnits == banner.sizeUnits))) {
			return;
		}
		[banner setSize:size sizeUnits:sizUnits isAdvisory:isAdvisory];
		[self layoutAllBannerViews];
	}
}

- (void)bannerSizeToContentsNoLayout:(void *)banner_handle
{
	[self bannerSizeToContents:banner_handle doLayout:NO];
}

- (void)bannerSizeToContents:(void *)banner_handle
{
	[self bannerSizeToContents:banner_handle doLayout:YES];
}

- (void)bannerSizeToContents:(void *)banner_handle doLayout:(BOOL)doLayout
{
	//XT_DEF_SELNAME;
	//XT_WARN_2(@"banner_handle=%ld doLayout=%d", banner_handle, doLayout);

	RETURN_IF_SHUTTING_DOWN_VM_THREAD;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner != nil) {
		CGFloat oldSizeOfContents = banner.sizeOfContents;
		NSUInteger oldSize = banner.size;
		NSUInteger oldSizeUnits = banner.sizeUnits;
		
		[banner callOnMainThread:@selector(mainThread_sizeToContents)];
		//XT_WARN_2(@"banner_handle=%ld sizeOfContents=%lf", banner_handle, banner.sizeOfContents);

		if (doLayout) {
			BOOL sizeHasChanged = ((banner.sizeOfContents != oldSizeOfContents) ||
								   (banner.size != oldSize) ||
								   (banner.sizeUnits != oldSizeUnits));
			if (sizeHasChanged) {
				/*
				if (banner.sizeOfContents != oldSizeOfContents) {
					XT_WARN_2(@"sizeHasChanged banner.sizeOfContents %lf != oldSizeOfContents %lf", banner.sizeOfContents, oldSizeOfContents);
				}
				if (banner.size != oldSize) {
					XT_WARN_2(@"sizeHasChanged banner.size %lu != oldSize %lu", banner.size, oldSize);
				}*/
				[self layoutAllBannerViews];
			}
		}
	}
}

- (void)bannerGoto:(void *)banner_handle
			   row:(NSUInteger)row
			column:(NSUInteger)column
{
	RETURN_IF_SHUTTING_DOWN_VM_THREAD;

	XTBannerTextHandler *banner = [self getBanner:banner_handle];
	if (banner != nil) {
		[banner gotoRow:row column:column];
	}
}

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

- (XTBannerTextHandler *)getBanner:(void *)handle
{
	XT_DEF_SELNAME;

	NSNumber *handleObj = [NSNumber numberWithUnsignedInteger:(NSUInteger)handle];
	XTBannerTextHandler *banner = [self.bannersByHandle objectForKey:handleObj];
	if (banner == nil) {
		XT_WARN_1(@"No banner with handle %lu", (NSUInteger)handle);
	}
	return banner;
}

- (void)traceBannerHierarchy
{
	//XT_DEF_SELNAME;

	if (! XT_TRACE_ON) {
		return;
	}
	
	XTBannerTextHandler *mainAreaBanner = [self getBanner:0];
	[mainAreaBanner traceWithIndentLevel:0];
}

- (void)layoutAllBannerViews
{
	//XT_DEF_SELNAME;

	RETURN_IF_SHUTTING_DOWN_VM_THREAD;
	//if ([NSThread isMainThread]) {
	//	XT_WARN_0(@"should not be called on main thread");
	//}
	[self callOnMainThread:@selector(mainThread_layoutAllBannerViews)];
}


