
#include "grsp.h"

#ifndef PandaWave_RESOURCES
#include "RevengeResources.h"
#endif

#include "RevengeApp.h"
#include <XMessages.h>
#include "tagpick.h"
#include <assert.h>
#include <XPopup.h>
#include <XWindow.h>


// ==============================  BYTE SWAPPING DATA  ========================================
byte_swap_code ground_sprite_byte_swapping_data[]=
{
	_begin_bs_array, GROUND_SPRITE_LAYERS_PER_MAP,

	_4byte, // sprites
	_4byte, // mask_offset
	_4byte, // mask_length
	4,		// mask_data_ptr at runtime
	_2byte, // density
	9*2,	// padding
	GROUND_SPRITE_NAME_LENGTH+1,
	
	_end_bs_array
};


// ==============================  EDIT WINDOW  ========================================
void edit_grsp( tag_entry* e )
{
	TgrspEditForm* form = new TgrspEditForm( e );
	form->AttachWindow( 1032 );
}

void defaultnew_grsp( tag_entry* e )
{
	ground_sprites_definition temp;
	memset( &temp, 0, sizeof(temp) );
	for (int i = 0; i < GROUND_SPRITE_LAYERS_PER_MAP; ++i) {
		temp.layers[i].sprites = -1;
	}
	byte_swap_data_be( "new ground sprite", &temp, sizeof(temp), 1, ground_sprite_byte_swapping_data );
	set_entry_data( e, &temp, sizeof(temp), false );
}

void dependency_grsp( tag_entry *e )
{
	ground_sprites_definition def;
	load_tag_data_into_struct( "grsp", e, &def, sizeof(ground_sprites_definition), 1, ground_sprite_byte_swapping_data);
	for (int i = 0; i < GROUND_SPRITE_LAYERS_PER_MAP; ++i)
	{
		add_tag_dependency( 'spri', def.layers[i].sprites );
	}
}


// ==============================  DISPATCH  ========================================
BEGINDISPATCH(TgrspEditForm,TTagEditForm)
	DISPATCHTABLE(KXGControlClick,TgrspEditForm::DoControlClick)
	DISPATCHTABLE(KXGKeyClick,TgrspEditForm::DoKeyClick)
ENDDISPATCH


TgrspEditForm::TgrspEditForm( struct tag_entry *e ) : TTagEditForm( e )
{
	memset( &def, 0, sizeof(def) );
	fNeedCommit = false;
}

TgrspEditForm::~TgrspEditForm()
{
	free_data();
}

// ==============================  INITIALIZE FORM =======================================
void TgrspEditForm::DoFormInitialize()
{
	TTagEditForm::DoFormInitialize();
}


// ==============================  INPUT HANDLING  ========================================
long TgrspEditForm::DoControlClick( long arg, void *ptr )
{
#ifdef __MWERKS__
	#pragma unused(ptr)
#endif
	int layer = arg / 100 - 10;
	int ctrl = arg % 100;
	if (layer >= 0 && layer < GROUND_SPRITE_LAYERS_PER_MAP) {
		switch (ctrl) {
			case 0:
				tag new_tag = pick_tag_of_type('spri', GetTag( arg ), fEntry  );
				if (new_tag != 0) {
					SetTag( arg, 'spri', new_tag);
					def.layers[layer].sprites = new_tag;
					fNeedCommit = true;
				} return 0;
			case 1:
				tag_entry *e = get_entry( 'spri', GetTag( arg-1 ) );
				if (e) {
					TRevengeApp::OpenItem( e );
				} return 0;
			case 3: { // file
					XGFileSpecifier *fs = 0;
					
					#if OPT_MACOS
						fs = XGFileSpecifier::OpenDialog( 130 );
					#endif
					
					#if OPT_WINOS
						fs = XGFileSpecifier::OpenDialog( "JPEG|*.jpg|All Files|*.*","jpg" );
					#endif
					
					if (fs) {
						fs->GetName( def.layers[layer].name );
						SetText( 1000 + layer * 100 + 2, def.layers[layer].name );
						XGFile f;
						f.Open( fs, false );
						def.layers[layer].mask_length = f.GetEOF();
						if (def.layers[layer].mask_data) {
							free( def.layers[layer].mask_data );
						}
						def.layers[layer].mask_data = malloc( def.layers[layer].mask_length );
						f.Read( def.layers[layer].mask_length, def.layers[layer].mask_data );
						f.Close();
						
						delete fs;
						fNeedCommit = true;
					}
				} return 0;
			case 4: { // clear
					if (def.layers[layer].mask_data) {
						free( def.layers[layer].mask_data );
						fNeedCommit = true;
					}
					memset( def.layers[layer].name, 0, sizeof(def.layers[layer].name) );
					def.layers[layer].mask_offset = 0;
					def.layers[layer].mask_length = 0;
					def.layers[layer].mask_data = 0;
					SetText( 1000 + layer * 100 + 2, "(none)" );
				} return 0;
		}
	}
	
	return -1;
}

long TgrspEditForm::DoKeyClick( long arg, void *ptr )
{
#ifdef __MWERKS__
	#pragma unused(ptr)
#endif
	int layer = arg / 100 - 10;
	int ctrl = arg % 100;
	if (layer >= 0 && layer < GROUND_SPRITE_LAYERS_PER_MAP) {
		switch (ctrl) {
			case 5:
				fNeedCommit = true;
				return 0;
		}
	}
	
	return -1;
}


		
// ========================================  SAVE TO TAG  ==================================================
void TgrspEditForm::CommitToTag()
{
	int size = sizeof(ground_sprites_definition);
	int i;
	
	for (i = 0; i < GROUND_SPRITE_LAYERS_PER_MAP; ++i) {
		def.layers[i].density = GetInt( 1000 + 100 * i + 5 );
		if (def.layers[i].mask_data && def.layers[i].mask_length) {
			bool found_zero = false;
			for (int j = 0; j < sizeof(def.layers[i].name); ++j) {
				if (found_zero) {
					def.layers[i].name[j] = 0;
				} else if (!def.layers[i].name[j]) {
					found_zero = true;
				}
			}
			def.layers[i].mask_offset = size;
			size += def.layers[i].mask_length;
		} else {
			memset( def.layers[i].name, 0, sizeof(def.layers[i].name) );
			def.layers[i].mask_offset = 0;
			def.layers[i].mask_length = 0;
			def.layers[i].mask_data = 0;
		}
	}
	byte *buf = (byte *)malloc( size );
	if (!buf) return;
	byte_swap_move_be( "ground sprite commit", buf, &def, sizeof(def), 1, ground_sprite_byte_swapping_data );
	for (i = 0; i < GROUND_SPRITE_LAYERS_PER_MAP; ++i) {
		if (def.layers[i].mask_data && def.layers[i].mask_length) {
			memcpy( buf + def.layers[i].mask_offset, def.layers[i].mask_data, def.layers[i].mask_length );
		}
	}
	
	set_entry_data( fEntry, buf, size, true );
	
	fNeedCommit = false;
}


// ========================================  RELOAD TAG  ==================================================
void TgrspEditForm::ReloadTag()
{
	free_data();
	const void *tagdata;
	unsigned taglength;
	if (!get_entry_data( fEntry, &tagdata, &taglength )) return;
	byte_swap_move_be( "ground sprites", &def, tagdata, sizeof(def), 1, ground_sprite_byte_swapping_data );
	for (int i = 0; i < GROUND_SPRITE_LAYERS_PER_MAP; ++i) {
		int base = 1000 + 100 * i;
		
		SetTag( base+0, 'spri', def.layers[i].sprites );
		
		if (def.layers[i].mask_length) {
			def.layers[i].mask_data = malloc( def.layers[i].mask_length );
			memcpy( def.layers[i].mask_data, (const char *)tagdata + def.layers[i].mask_offset, def.layers[i].mask_length );
			SetText( base+2, def.layers[i].name );
		} else {
			def.layers[i].mask_data = 0;
			SetText( base+2, "(none)" );
		}
		
		SetInt( base+5, def.layers[i].density );
	}
	
	fNeedCommit = false;
}


// ========================================  TAG NEEDS UPDATING  ==================================================
bool TgrspEditForm::NeedCommit()
{
	return fNeedCommit;
}


void TgrspEditForm::free_data()
{
	for (int i = 0; i < GROUND_SPRITE_LAYERS_PER_MAP; ++i) {
		if (def.layers[i].mask_data) {
			free( def.layers[i].mask_data );
		}
	}

	memset( &def, 0, sizeof(def) );
}

