//
//  osxtads_output.m
//  XTads
//
//  Created by Rune Berg on 12/07/2020.
//  Copyright © 2020 Rune Berg. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "osxtads_support.h"


int osxtads_show_terp_copyright_at_game_start()
{
	BOOL res = [getGameRunner() showTerpCopyrightAtGameStart];
	return (int)res;
}

/*
 *   Enter HTML mode
 */
void os_start_html()
{
	XTOSIFC_TRACE_ENTRY(@"os_start_html");
	
	[getGameRunner() setHtmlMode:YES];
}

/*
 *   exit HTML mode
 */
void os_end_html()
{
	XTOSIFC_TRACE_ENTRY(@"os_end_html");

	[getGameRunner() setHtmlMode:NO];
}

/*
 *   get the status line mode
 */
int os_get_status()
{
	XTOSIFC_DEF_SELNAME(@"os_get_status");

	int res = (int) getGameRunner().statusLineMode;
	XTOSIFC_TRACE_1(@"--> %d", res);
	
	return res;
}

/*
 *   Set the status line mode.  There are three possible settings:
 *
 *   0 -> main text mode.  In this mode, all subsequent text written with
 *   os_print() and os_printz() is to be displayed to the main text area.
 *   This is the normal mode that should be in effect initially.  This mode
 *   stays in effect until an explicit call to os_status().
 *
 *   1 -> statusline mode.  In this mode, text written with os_print() and
 *   os_printz() is written to the status line, which is usually rendered as
 *   a one-line area across the top of the terminal screen or application
 *   window.  In statusline mode, leading newlines ('\n' characters) are to
 *   be ignored, and any newline following any other character must change
 *   the mode to 2, as though os_status(2) had been called.
 *
 *   2 -> suppress mode.  In this mode, all text written with os_print() and
 *   os_printz() must simply be ignored, and not displayed at all.  This mode
 *   stays in effect until an explicit call to os_status().
 */
void os_status(int stat)
{
	XTOSIFC_DEF_SELNAME(@"os_status");
	XTOSIFC_TRACE_1(@"stat=%d", stat);

	/* see what mode we're setting */
	switch(stat)
	{
		case 0:
		default:
			/* turn off status line mode */
			getGameRunner().statusLineMode = STATUS_LINE_MODE_MAIN;
			break;
			
		case 1:
			/* turn on status line mode */
			getGameRunner().statusLineMode = STATUS_LINE_MODE_STATUS;
			break;
			
		case 2:
			getGameRunner().statusLineMode = STATUS_LINE_MODE_SUPPRESS;
			break;
	}
}

/*
 *   clear the screen
 */
void oscls()
{
	XTOSIFC_TRACE_ENTRY(@"oscls");
	
	[getGameRunner() clearScreen];
}

/*
 *   Set the game title.  The output layer calls this routine when a game
 *   sets its title (via an HTML <title> tag, for example).  If it's
 *   convenient to do so, the OS layer can use this string to set a window
 *   caption, or whatever else makes sense on each system.  Most
 *   character-mode implementations will provide an empty implementation,
 *   since there's not usually any standard way to show the current
 *   application title on a character-mode display.
 */
// amoi.gam calls this(?)
void os_set_title(const char *title)
{
	NSString *s = [getGameRunner() makeString:title];
	[getGameRunner() setGameTitle:s];
}

/*
 *   Set text attributes.  We can ignore these if we're in HTML mode,
 *   because we can count on the caller sending us HTML markups directly.
 *   When we're not in HTML mode, though, we need to supply the appropriate
 *   formatting.
 */
void os_set_text_attr(int attrs)
{
	XTOSIFC_DEF_SELNAME(@"os_set_text_attr");
	XTOSIFC_TRACE_1(@"%lu", attrs);
	
    if (getGameRunner().htmlMode)
        return;
	
	// Impl here is like the htmltads one, where only OS_ATTR_HILITE is considered:
	BOOL hiliteMode = ((attrs & OS_ATTR_HILITE) != 0);
	[getGameRunner() setHiliteMode:hiliteMode];
}

/*
 *   set the score value
 */
void os_score(int cur, int turncount)
{
	XTOSIFC_DEF_SELNAME(@"os_score");
	XTOSIFC_TRACE_2(@"%d %d", cur, turncount);

	NSString *scoreString = [NSString stringWithFormat:@"%d/%d", cur, turncount];
	[getGameRunner() showScore:scoreString];
}

/*
 *   display a string in the score area in the status line
 */
void os_strsc(const char *p)
{
	XTOSIFC_DEF_SELNAME(@"os_strsc");
	XTOSIFC_TRACE_1(@"\"%s\"", p);
	
	NSString *scoreString = [getGameRunner() makeString:p];
	[getGameRunner() showScore:scoreString];
}

/*
 *   use plain ascii mode for the display
 */
void os_plain()
{
	//LOG_CALL_TO_UNIMPLEMENTED_FUNCTION(@"os_plain");
	/* ignore this -- we can only use the HTML mode */
}

/*
 *   Set non-stop mode.  This tells the OS layer that it should disable any
 *   MORE prompting it would normally do.
 *
 *   This routine is needed only when the OS layer handles MORE prompting; on
 *   character-mode platforms, where the prompting is handled in the portable
 *   console layer, this can be a dummy implementation.
 */
void os_nonstop_mode(int flag)
{
	XTOSIFC_DEF_SELNAME(@"os_nonstop_mode");
	XTOSIFC_TRACE_1(@"\"%d\"", flag);

	[getGameRunner() setNonstopMode:flag];
}

void os_print(const char *str, size_t len) // str may not end with a \0
{
	if (XTOSIFC_TRACE_ON) {
		XTOSIFC_DEF_SELNAME(@"os_print");
		char *buf = malloc(len * sizeof(char) + 1); // +1 for \0
		strncpy(buf, str, len);
		buf[len] = '\0';
		XTOSIFC_TRACE_1(@"str=\"%s\"", buf);
		free(buf);
	}
	
	NSString *s = [getGameRunner() makeString:str len:len];
	[getGameRunner() printOutput:s];
}

/*
 *   write a string
 */
void os_printz(const char *str)
{
    os_print(str, strlen(str));
}

/*
 *   flush any buffered display output
 */
void os_flush()
{
	XTOSIFC_TRACE_ENTRY(@"os_flush");
	
	[getGameRunner() flushOutput];
}

/*
 *   Update the display - process any pending drawing immediately.  This
 *   only needs to be implemented for operating systems that use
 *   event-driven drawing based on window invalidations; the Windows and
 *   Macintosh GUI's both use this method for drawing window contents.
 *
 *   The purpose of this routine is to refresh the display prior to a
 *   potentially long-running computation, to avoid the appearance that the
 *   application is frozen during the computation delay.
 *
 *   Platforms that don't need to process events in the main thread in order
 *   to draw their window contents do not need to do anything here.  In
 *   particular, text-mode implementations generally don't need to implement
 *   this routine.
 *
 *   This routine doesn't absolutely need a non-empty implementation on any
 *   platform, but it will provide better visual feedback if implemented for
 *   those platforms that do use event-driven drawing.
 */
void os_update_display()
{
	//LOG_CALL_TO_UNIMPLEMENTED_FUNCTION(@"os_update_display");
}
