/*
 * Edit.c
 * Part of !GameID  Musus Umbra 1997
 */

#include "gameid.h"			/* database handling functions & types */
#include "fileio.h"			/* File IO routines */
#include "iconnums.h"		/* icon numbers -> #define mappings */
#include "core.h"			/* global resources */
#include "extract.h"		/* extract ID info from a game file */

#include "query.h"			/* a neat query dialog handler */
#include "chooseres.h"		/* contains a 'leafname()' function we want */

#include "Desklib:Core.h"
#include "Desklib:Wimp.h"
#include "Desklib:Msgs.h"
#include "Desklib:Resource.h"
#include "Desklib:Event.h"
#include "Desklib:EventMsg.h"
#include "Desklib:Sprite.h"
#include "Desklib:Template.h"
#include "Desklib:Window.h"
#include "Desklib:Icon.h"
#include "Desklib:Menu.h"
#include "Desklib:Screen.h"
#include "Desklib:Handler.h"
#include "Desklib:WimpSWIs.h"
#include "Desklib:Sound.h"
#include "Desklib:Error.h"
#include "Desklib:Hourglass.h"
#include "Desklib:File.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>


static gamelist games = NULL;
static window_handle edit_win = 0;
static char msg_file[260];
static game_id_node game_id;
static menu_ptr short_menu = NULL;

static icon_handle red_icns[] = { MAIN_RELEASE, MAIN_SERIAL, MAIN_SIZE,
									MAIN_SNAME, MAIN_LNAME, MAIN_ADD, -1 };



static int msm_count_games( void )
{
	game_node *srch;
	int g = 0;
	for ( srch=games ; srch ; srch=srch->next )
		g++;
	return g;
}



static void make_short_menu( void )
{
	int entries = msm_count_games();
	game_node *g;
	menu_item *i;
	if ( short_menu ) { free(short_menu); short_menu = NULL; }
	if ( !entries ) { return; }
	short_menu = malloc( sizeof(menu_block) + entries*sizeof(menu_item) );
	if ( !short_menu ) { return; }
	Msgs_Lookup("game.title",short_menu->title,wimp_MAXNAME);
	short_menu->titlefore = short_menu->workfore = 7;
	short_menu->titleback = 2;
	short_menu->workback = 0;
	short_menu->width = 12*16;
	short_menu->height = 44;
	short_menu->gap = 0;
	g = games; i = (menu_item*) ( ((int)short_menu) + sizeof(menu_block) );
	while ( g )
	{
		i->menuflags.value = i->iconflags.value = 0;
		i->menuflags.data.notifysub = 1;
		i->submenu.value = (int) g;
		i->iconflags.data.text = 1;
		i->iconflags.data.foreground = 7;
		i->iconflags.data.background = 0;
		strncpy(i->icondata.text,g->s,wimp_MAXNAME);
		i++;
		g = g->next;
	}
	i--;
	i->menuflags.data.last = 1;
}


static BOOL Hnd_MenuWarning( event_pollblock *b, void *ref )
{
	window_handle	fn_win;
	game_node		*game;
	int 			x;
	int 			y;
	char			buffer[64];
	if ( menu_currentopen != short_menu ) { return FALSE; }
	fn_win = Window_Create( "fullname", template_TITLEMIN );
	game = (game_node*) b->data.message.data.menuwarn.id;
	x = b->data.message.data.menuwarn.openpos.x;
	y = b->data.message.data.menuwarn.openpos.y;
	Msgs_printf( buffer,"game.full",game->s );
	Window_SetTitle( fn_win, buffer );
	Icon_SetText( fn_win, FULL_NAME, game->l );
	Event_Claim( event_CLOSE, fn_win, event_ANY, Handler_DeleteWindow, NULL );
	Wimp_CreateSubMenu( (menu_ptr) fn_win, x, y );
	return TRUE;
}

static BOOL Hnd_MenuSelection( event_pollblock *b, void *ref )
{
	menu_item *items;
	game_node *game;
	if ( menu_currentopen!=short_menu ) { return FALSE; }
	items = (menu_item*) ( ((int)short_menu) + sizeof(menu_block) );
	game = (game_node*) items[b->data.selection[0]].submenu.value;
	Icon_SetText( edit_win, MAIN_SNAME, game->s );
	Icon_SetText( edit_win, MAIN_LNAME, game->l );
	free(short_menu);
	short_menu = NULL;
	return TRUE;
}


static void colour_icons( int red )
{
	icon_handle *p = red_icns;
	int  c;
	c = red ? 11 : 7;
	while ( *p>=0 )
	{
		Icon_SetForeColour( edit_win, *p, c );
		p++;
	}
}


static void update_title_bar( void )
{
	static char title_text[64] = "";
	static char *asterisk = 0;
	static int old_state = 1;
	if ( old_state == modified ) { return; }
	if ( !asterisk )
	{
		Msgs_Lookup("task.name",title_text,64);
		asterisk = title_text + strlen(title_text);
	}
	if ( modified )
		strcpy(asterisk," *");
	else
		*asterisk = 0;
	Window_SetTitle( edit_win, title_text );
	old_state = modified;
}



static BOOL Hnd_EditClose( event_pollblock *b, void *ref )
{
	if ( modified )
	{
		if ( !query_box("close.t","close.m","close.n","close.y") )
			return TRUE;
	}
	delete_list( games );
	games = NULL;
	modified = 0;
	Window_Delete( edit_win );
	edit_win = 0;
	if ( short_menu ) { free(short_menu); short_menu=NULL; }
	return TRUE;
}


static BOOL Hnd_EditClick( event_pollblock *b, void *ref )
{
	if ( b->data.mouse.button.data.menu )
	{
		int x = b->data.mouse.pos.x - 16;
		int y = b->data.mouse.pos.y + 16;
		Menu_Show( win_menu, x, y );
		return TRUE;
	}
	return FALSE;
}


static void load_game( char *filename )
{
	char tmp[7];
	char buffer[24];
	game_node *match;
	if ( extract_header_info( filename ) )
	{
		Sound_SysBeep();
		query_box( "badgame.t", "badgame.m", 0, "badgame.y" );
		return;
	}
	Icon_SetText( edit_win, MAIN_FILENAME, filename );
	Icon_SetInteger( edit_win, MAIN_RELEASE, h_release );
	Icon_SetInteger( edit_win, MAIN_SIZE, story_size );
	Icon_printf( edit_win, MAIN_VERSION, "V%d", h_version );
	memcpy( tmp, h_serial, 6 );
	tmp[7] = 0;
	Icon_SetText( edit_win, MAIN_SERIAL, tmp );
	game_id.size = story_size;
	game_id.release = h_release;
	memcpy(game_id.serial,tmp,6);
	match = identify_game( games, &game_id );
	if ( match )
	{
		colour_icons(0);
		Icon_SetText( edit_win, MAIN_SNAME, match->s );
		Icon_SetText( edit_win, MAIN_LNAME, match->l );
		Msgs_Lookup("game.rename",buffer,24);
	}
	else
	{
		colour_icons(1);
		strncpy(buffer,leafname(filename),8);
		Icon_SetText( edit_win, MAIN_SNAME, buffer );
		Icon_SetText( edit_win, MAIN_LNAME, leafname(filename) );
		Msgs_Lookup("game.add",buffer,24);
		Sound_SysBeep();
	}
	Icon_SetText( edit_win, MAIN_ADD, buffer );
	Icon_Unshade( edit_win, MAIN_ADD );
	Icon_Unshade( edit_win, MAIN_LIST );
	Icon_Unshade( edit_win, MAIN_SNAME );
	Icon_Unshade( edit_win, MAIN_LNAME );
	Icon_SetCaret( edit_win, MAIN_SNAME );
	update_title_bar();
}



static BOOL Hnd_EditList( event_pollblock *b, void *ref )
{
	static int claimed_menuwarnings = 0;
	if ( !claimed_menuwarnings )
	{
		EventMsg_Claim( message_MENUWARNING, event_ANY, Hnd_MenuWarning, 0 );
		Event_Claim( event_MENU, event_ANY, event_ANY, Hnd_MenuSelection, 0 );
		claimed_menuwarnings = 1;
	}
	make_short_menu();
	if ( short_menu )
		Menu_PopUp( short_menu, edit_win, MAIN_LIST );
	else
		query_box( "menumem.t","menumem.m",0,"menumen.y" );
	return TRUE;
}






static BOOL Hnd_EditLoad( event_pollblock *b, void *ref )
{
	char filename[260];
	message_block mb = b->data.message;
	icon_handle sndr_i = b->data.message.data.dataload.icon;
	window_handle sndr_w = b->data.message.data.dataload.window;
	/* First, check that we've been offered a z-code game */
	if ( b->data.message.data.dataload.filetype != FILETYPE_ZCODE )
	{
		Sound_SysBeep();
		query_box( "notgame.t", "notgame.m", 0, "notgame.y" );
		return TRUE;
	}
	strcpy(filename,b->data.message.data.dataload.filename);
	mb.header.yourref = mb.header.myref;
	mb.header.action = message_DATALOADACK;
	Wimp_SendMessage( event_ACK , &mb, sndr_w, sndr_i );
	load_game( filename );
	return TRUE;
}



static void init_edit_win( void )
{
	char buffer[64];
	Msgs_Lookup("game.drop",buffer,64);
	Icon_SetText( edit_win, MAIN_FILENAME, buffer );
	Icon_SetText( edit_win, MAIN_LNAME, buffer );
	Icon_SetText( edit_win, MAIN_SNAME, "" );
	Icon_SetText( edit_win, MAIN_RELEASE, "" );
	Icon_SetText( edit_win, MAIN_SERIAL, "" );
	Icon_SetText( edit_win, MAIN_VERSION, "" );
	Icon_SetText( edit_win, MAIN_SIZE, "" );
	Msgs_Lookup("game.add",buffer,24);
	Icon_SetText( edit_win, MAIN_ADD, buffer );
	Icon_Shade( edit_win, MAIN_SNAME );
	Icon_Shade( edit_win, MAIN_LNAME );
	Icon_Shade( edit_win, MAIN_LIST );
	Icon_Shade( edit_win, MAIN_ADD );
	update_title_bar();
}



static BOOL Hnd_EditAdd( event_pollblock *b, void *ref )
{
	char buffer[24];
	char *new_s = Icon_GetTextPtr( edit_win, MAIN_SNAME );
	char *new_l = Icon_GetTextPtr( edit_win, MAIN_LNAME );
	games = add_game_id( games, new_s, new_l, &game_id );
	Msgs_Lookup("game.rename",buffer,24);
	Icon_SetText( edit_win, MAIN_ADD, buffer );
	colour_icons(0);
	modified = 1;
	update_title_bar();
	return TRUE;
}



static BOOL Hnd_EditKey( event_pollblock *b, void *ref )
{
	if ( b->data.key.code != 13 )
	{
		Wimp_ProcessKey( b->data.key.code );
		return TRUE;
	}
	Icon_Select( edit_win, MAIN_ADD );
	Icon_ClickWait( 33 );
	Icon_Deselect( edit_win, MAIN_ADD );
	return Hnd_EditAdd(b,ref);
}




/* Open the edit window on 'app_dir's GameIDs message file */
void start_edit( char *app_dir )
{
	if ( modified )	/* already editing? */
	{
		if ( !query_box("owrite.t","owrite.m","owrite.n","owrite.y") )
			return;
	}
	sprintf( msg_file, "%s.Resources.GameIDs",app_dir);
	if ( !File_Exists( msg_file ) )
	{
		query_box( "nomsgs.t","nomsgs.m",NULL,"nomsgs.y" );
		return;
	}
	if ( games )
	{
		delete_list(games);
		games = NULL;
	}
	Hourglass_On();
	games = readfile( msg_file );
	Hourglass_Off();
	modified = 0;
	if ( !edit_win )
	{
		edit_win = Window_Create( "about", template_TITLEMIN );
		Window_Show( edit_win, open_CENTERED );
		Event_Claim( event_CLOSE, edit_win, event_ANY, Hnd_EditClose, NULL );
		Event_Claim( event_CLICK, edit_win, event_ANY, Hnd_EditClick, NULL );
		Event_Claim( event_CLICK, edit_win, MAIN_LIST, Hnd_EditList, NULL );
		Event_Claim( event_CLICK, edit_win, MAIN_ADD, Hnd_EditAdd, NULL );
		Event_Claim( event_KEY, edit_win, MAIN_LNAME, Hnd_EditKey, NULL ); 
		EventMsg_Claim( message_DATALOAD, edit_win, Hnd_EditLoad, NULL );
	}
	else
	{
		Window_BringToFront(edit_win);
	}
	init_edit_win();
}


static int copy_file( char *from, char *to )
{
	char buffer[260];
	FILE *i, *o;
	i = fopen( from, "r" );
	if ( !i ) { return 1; }
	o = fopen( to, "w" );
	if ( !o ) { fclose(i); return 2; }
	while ( fgets(buffer,260,i) )
	{
		fputs(buffer,o);
	}
	fclose(i);
	fclose(o);
	return 0;
}


/* Save the current database */
void start_save( void )
{
	FILE *ostream;
	char *temp_file;
	temp_file = "<wimp$scrap>";
	if ( copy_file( msg_file, temp_file ) )
	{
		query_box("nosave1.t","nosave1.m",NULL,"nosave1.y");
		return;
	}
	ostream = fopen( msg_file, "w" );
	if ( ostream )
	{
		Hourglass_On();
		copy_comments( ostream, temp_file );
		writefile( ostream, games );
		fclose(ostream);
		remove(temp_file);
		Hourglass_Off();
		modified = 0;
		update_title_bar();
	}
	else
	{
		query_box("nosave2.t","nosave2.m",NULL,"nosave2.y");
	}
}


