//
//  XTOpenForTestingController.m
//  XTads
//
//  Created by Rune Berg on 05/01/2018.
//  Copyright © 2018 Rune Berg. All rights reserved.
//

#import "XTOpenForTestingController.h"
#import "XTFileNameHelper.h"
#import "XTStringUtils.h"
#import "XTUIUtils.h"
#import "XTConstants.h"
#import "XTLogger.h"
#import "XTAllocDeallocCounter.h"


@interface XTOpenForTestingController ()

@property XTFileNameHelper *fileNameHelper;

@property BOOL hasFinished;

@property NSArray *selectableCommandScriptActions;

@property (weak) IBOutlet NSTextField *gameFileUrlTextField;
@property (weak) IBOutlet NSButton *saveSelectFileButton;
@property (weak) IBOutlet NSTextField *saveFileUrlTextField;
@property (weak) IBOutlet NSPopUpButton *commandScriptActionPopupButtom;
@property (weak) IBOutlet NSTextField *commandScriptFileUrlTextField;
@property (weak) IBOutlet NSButton *commandScriptSelectFileButton;
@property (weak) IBOutlet NSButton *printGameTextOnReplayCheckbox;
@property (weak) IBOutlet NSButton *transcriptCaptureCheckbox;
@property (weak) IBOutlet NSTextField *transcriptFileUrlTextField;
@property (weak) IBOutlet NSButton *transcriptSelectFileButton;
@property (weak) IBOutlet NSButton *dontSeedRNGCheckbox;
@property (weak) IBOutlet NSButton *openButton;

@end


@implementation XTOpenForTestingController

static XTLogger* logger;

#define KEY_ACTION @"action"
#define KEY_LABEL @"label"

NSRange noSelectionRange;

+ (void)initialize
{
	logger = [XTLogger loggerForClass:[XTOpenForTestingController class]];
	noSelectionRange = NSMakeRange(0, 0);
}

OVERRIDE_ALLOC_FOR_COUNTER
OVERRIDE_DEALLOC_FOR_COUNTER

+ (XTOpenForTestingController *)controllerWithParams:(XTRunGameParams *)runGameParams;
{
	XTOpenForTestingController *wc = [[XTOpenForTestingController alloc] initWithWindowNibName:@"XTOpenForTestingController"];
	if (runGameParams != nil) {
		wc.runGameParams = runGameParams;
	}
	return wc;
}

- (instancetype)initWithWindow:(NSWindow *)window;
{
	self = [super initWithWindow:window];
	if (self != nil) {
		_runGameParams = [XTRunGameParams new];
		_fileNameHelper = [XTFileNameHelper helper];
		_hasFinished = NO;
		_selectableCommandScriptActions = @[
			  @{KEY_ACTION: [NSNumber numberWithInteger:XT_CMD_SCRIPT_ACTION_NONE],
				KEY_LABEL: @"None"},
			  @{KEY_ACTION: [NSNumber numberWithInteger:XT_CMD_SCRIPT_ACTION_RECORD],
				KEY_LABEL: @"Record"},
			  @{KEY_ACTION: [NSNumber numberWithInteger:XT_CMD_SCRIPT_ACTION_REPLAY],
				KEY_LABEL: @"Replay"}
			  ];
	}
	return self;
}

- (void)windowDidLoad
{
    [super windowDidLoad];
	[self.window center];
	[self recalcUiState];
}

- (IBAction)open:(id)sender
{
	[self finishWithResult:YES];
}

- (IBAction)cancel:(id)sender
{
	[self finishWithResult:NO];
}

- (IBAction)selectGame:(id)sender
{
	NSURL *defaultDir = [self.fileNameHelper findDefaultDirectoryForFileType:XTadsFileNameDialogFileTypeGame];
	NSOpenPanel* panel = [XTUIUtils makeFileOpenPanelWithTitle:XT_DIALOG_TITLE_GAME_FILE
											 allowedExtensions: @[XT_FILE_EXTENSION_TADS2_GAME, XT_FILE_EXTENSION_TADS3_GAME]
													defaultDir:defaultDir];
	
	[panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
		if (result == NSFileHandlingPanelOKButton) {
			self.runGameParams.gameFileUrl = [[panel URLs] objectAtIndex:0];
			self.runGameParams.saveFileUrl = nil;
			self.runGameParams.commandScriptFileUrl = nil;
			self.runGameParams.transcriptFileUrl = nil;
		}
		[self recalcUiState];
	}];
}

- (IBAction)selectSave:(id)sender
{
	XT_DEF_SELNAME;

	NSURL *defaultDir = [self.fileNameHelper findDefaultDirectoryForFileType:XTadsFileNameDialogFileTypeSavedGame];

	NSString *titlePrefix;
	NSString *allowedExt;
	NSString *typeDescr;
	NSArray *allowedExtsList;
	if (! [self haveT3Game]) {
		/*
		titlePrefix = XT_FILE_DIALOG_TITLE_PREFIX_TADS2_SAVE;
		allowedExt = XT_FILE_EXTENSION_TADS2_SAVE;
		typeDescr = XT_FILE_TYPE_DESCR_TADS2_SAVE;
		allowedExtsList = @[XT_FILE_EXTENSION_TADS2_SAVE];
		 */
		XT_ERROR_0(@"Not supported by T2 VM");
		return;
	} else {
		titlePrefix = XT_FILE_DIALOG_TITLE_PREFIX_TADS3_SAVE;
		allowedExt = XT_FILE_EXTENSION_TADS3_SAVE;
		typeDescr = XT_FILE_TYPE_DESCR_TADS3_SAVE;
		allowedExtsList = @[XT_FILE_EXTENSION_TADS3_SAVE];
	}
	
	NSString *dialogTitle = [NSString stringWithFormat:XT_FILE_DIALOG_TITLE_FORMAT,
							 titlePrefix, typeDescr, allowedExt];

	NSOpenPanel* panel = [XTUIUtils makeFileOpenPanelWithTitle:dialogTitle
											 allowedExtensions:allowedExtsList
													defaultDir:defaultDir];
	
	[panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
		if (result == NSFileHandlingPanelOKButton) {
			self.runGameParams.saveFileUrl = [[panel URLs] objectAtIndex:0];
		}
		[self recalcUiState];
	}];
}

- (IBAction)selectCommandScriptFile:(id)sender
{
	XT_DEF_SELNAME;

	NSURL *defaultDir = [self.fileNameHelper findDefaultDirectoryForFileType:XTadsFileNameDialogFileTypeCommandScript];

	if (self.runGameParams.commandScriptAction == XT_CMD_SCRIPT_ACTION_RECORD) {
		NSString *dialogTitle = [NSString stringWithFormat:XT_FILE_DIALOG_TITLE_FORMAT,
								 XT_FILE_DIALOG_TITLE_PREFIX_NEW_COMMAND_LOG, XT_FILE_TYPE_DESCR_COMMAND_LOG, XT_FILE_EXTENSION_COMMAND_LOG];

		NSString *defaultBasename = [self.fileNameHelper findDefaultFileBasenameForGameFileUrl:self.runGameParams.gameFileUrl
																					  fileType:XTadsFileNameDialogFileTypeCommandScript];
		NSSavePanel *panel = [XTUIUtils makeFileSavePanelWithTitle:dialogTitle
												 allowedExtensions:@[XT_FILE_EXTENSION_COMMAND_LOG]
														defaultDir:defaultDir
												   defaultBasename:defaultBasename];
		
		[panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result){
			if (result == NSFileHandlingPanelOKButton) {
				self.runGameParams.commandScriptFileUrl = [panel URL];
			}
			[self recalcUiState];
		}];
		
	} else if (self.runGameParams.commandScriptAction == XT_CMD_SCRIPT_ACTION_REPLAY) {
		NSString *dialogTitle = [NSString stringWithFormat:XT_FILE_DIALOG_TITLE_FORMAT,
								 XT_FILE_DIALOG_TITLE_PREFIX_EXISTING_COMMAND_LOG, XT_FILE_TYPE_DESCR_COMMAND_LOG, XT_FILE_EXTENSION_COMMAND_LOG];
		
		NSOpenPanel *panel = [XTUIUtils makeFileOpenPanelWithTitle:dialogTitle
												 allowedExtensions:@[XT_FILE_EXTENSION_COMMAND_LOG]
														defaultDir:defaultDir];
		[panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result){
			if (result == NSFileHandlingPanelOKButton) {
				self.runGameParams.commandScriptFileUrl = [panel URL];
			}
			[self recalcUiState];
		}];

	} else {
		XT_ERROR_0(@"No action for command script - should not happen");
		return;
	}
}

- (IBAction)selectTranscriptFile:(id)sender
{
	NSString *dialogTitle = [NSString stringWithFormat:XT_FILE_DIALOG_TITLE_FORMAT,
							 XT_FILE_DIALOG_TITLE_PREFIX_TRANSCRIPT, XT_FILE_TYPE_DESCR_TRANSCRIPT, XT_FILE_EXTENSION_TRANSCRIPT];

	NSURL *defaultDir = [self.fileNameHelper findDefaultDirectoryForFileType:XTadsFileNameDialogFileTypeTranscript];

	NSString *defaultBasename = [self.fileNameHelper findDefaultFileBasenameForGameFileUrl:self.runGameParams.gameFileUrl
																				  fileType:XTadsFileNameDialogFileTypeTranscript];
	NSSavePanel *panel = [XTUIUtils makeFileSavePanelWithTitle:dialogTitle
											 allowedExtensions:@[XT_FILE_EXTENSION_TRANSCRIPT]
													defaultDir:defaultDir
											   defaultBasename:defaultBasename];
	
	[panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result){
		if (result == NSFileHandlingPanelOKButton) {
			self.runGameParams.transcriptFileUrl = [panel URL];
		}
		[self recalcUiState];
	}];
}

- (IBAction)selectCommandScriptAction:(id)sender
{
	self.runGameParams.commandScriptFileUrl = nil;
	[self recalcUiState];
}

- (IBAction)selectTranscriptCapture:(id)sender
{
	self.runGameParams.transcriptFileUrl = nil;
	[self recalcUiState];
}

- (void)windowWillClose:(NSNotification *)notification
{
	[self finishWithResult:NO];
}

- (void)finishWithResult:(BOOL)result
{
	if (! self.hasFinished) {
		self.runGameParams.shouldOpen = result;
		[NSApp stopModal];
		self.hasFinished = YES;
	}
}

- (void)recalcUiState
{
	BOOL haveGameFile = [self haveGameFile];
	BOOL haveT3Game = [self haveT3Game];
	BOOL haveCommandScriptFile = (self.runGameParams.commandScriptFileUrl.absoluteString.length >= 1);
	BOOL haveTranscriptFile = (self.runGameParams.transcriptFileUrl.absoluteString.length >= 1);
	
	self.saveSelectFileButton.enabled = haveT3Game;

	self.commandScriptActionPopupButtom.enabled = haveGameFile;
	
	self.commandScriptSelectFileButton.enabled = (haveGameFile && self.runGameParams.commandScriptAction != XT_CMD_SCRIPT_ACTION_NONE);
	
	BOOL canPrintOnReplay = (haveT3Game && (self.runGameParams.commandScriptAction == XT_CMD_SCRIPT_ACTION_REPLAY));
	if (! canPrintOnReplay) {
		self.runGameParams.echoOutputFromCommandScriptReplay = NO;
	}
	self.printGameTextOnReplayCheckbox.enabled = canPrintOnReplay;
	
	BOOL haveConsistentCommandScriptSelections = ((self.runGameParams.commandScriptAction == XT_CMD_SCRIPT_ACTION_NONE) || haveCommandScriptFile);

	self.transcriptCaptureCheckbox.enabled = haveGameFile;
	self.transcriptSelectFileButton.enabled = (haveGameFile && self.runGameParams.captureTranscript);
	BOOL haveConsistentTranscriptSelections = ((! self.runGameParams.captureTranscript) || haveTranscriptFile);
	
	if (! haveGameFile) {
		self.runGameParams.dontSeedRandomizer = NO; // important that this is before .enabled state change
		self.dontSeedRNGCheckbox.enabled = NO;
	} else {
		if (! haveT3Game) {
			self.runGameParams.dontSeedRandomizer = NO;
		}
		self.dontSeedRNGCheckbox.enabled = haveT3Game;
	}

	self.openButton.enabled = (haveGameFile && haveConsistentCommandScriptSelections && haveConsistentTranscriptSelections);
	
	[self deselectTextIn:self.saveFileUrlTextField];
	[self deselectTextIn:self.gameFileUrlTextField];
	[self deselectTextIn:self.commandScriptFileUrlTextField];
	[self deselectTextIn:self.transcriptFileUrlTextField];
}

- (BOOL)haveGameFile
{
	return (self.runGameParams.gameFileUrl.absoluteString.length >= 1);
}

- (BOOL)haveT3Game
{
	return ([self haveGameFile] && [XTStringUtils isTads3GameUrl:self.runGameParams.gameFileUrl]);
}

- (void)deselectTextIn:(NSTextField *)textField
{
	textField.currentEditor.selectedRange = noSelectionRange;
}

@end
