
#include "obje.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>
#include <XDialog.h>
#include "formatters.h"
#include "vengeance_script.h"


// ==============================  BYTE SWAPPING DATA  ========================================
byte_swap_code object_definition_byte_swapping_data[]=
{
	_begin_bs_array, 1,
	
	// word flags;
	_2byte,
	
	// short_world_distance gravity; // world_distance/(ticks^2)
	// short_fixed elasticity; // how much velocity is preserved after a collision
	_2byte, _2byte,
	
	// short_world_distance terminal_velocity; // for gravity only
	_2byte,
	
	// short_fixed maximum_vitality, maximum_vitality_delta;
	// short_fixed scale_lower_bound, scale_delta;
	_2byte, _2byte,
	_2byte, _2byte,
	
	// short_fixed effect_modifiers[MAXIMUM_NUMBER_OF_EFFECT_MODIFIERS];
	_begin_bs_array, MAXIMUM_NUMBER_OF_EFFECT_MODIFIERS, _2byte, _end_bs_array,
	
	// short_fixed minimum_damage; // how much damage must be done before it takes effect
	_2byte,

	// short unused[7];
	7*sizeof(short),

	_end_bs_array
};

object_definition default_obje =
{
	0,
	0,
	0,
	0,
	0, 0,
	0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0,
	0, 0, 0, 0, 0, 0, 0
};


// ==============================  EDIT WINDOW  ========================================
void edit_obje( tag_entry* e )
{
	TobjeEditForm* form = new TobjeEditForm( e );
	form->AttachWindow( 1016 );
}

void defaultnew_obje( tag_entry *e )
{
	object_definition def;
	byte_swap_move_be( "obje", &def, &default_obje, sizeof(object_definition), 1, object_definition_byte_swapping_data );
	set_entry_data( e, &def, sizeof(def), false );
}

void dependency_obje( tag_entry *e )
{
#if 0 // no dependencies
	object_definition def;
	read_object_definition( &def, e );
#endif
}


// ==============================  READ TAG DATA  ========================================
bool read_object_definition( object_definition* def, tag_entry* e )
{
	return load_tag_data_into_struct( "obje", e, def, SIZEOF_STRUCT_OBJECT_DEFINITION, 1, object_definition_byte_swapping_data);
}


// ==============================  SAVE TAG DATA  ========================================
bool save_object_definition( object_definition* def, tag_entry* e )
{
	return save_tag_data_from_struct( "obje", e, def, SIZEOF_STRUCT_OBJECT_DEFINITION, 1, object_definition_byte_swapping_data);
}


// ==============================  READ TAG DATA (WITH ID) ========================================
bool read_object_definition( object_definition* def, tag id )
{
	tag_entry* e;
	
	assert( def );
	
	e = get_entry( 'obje', id );
	if( 0 == e ) {
		return FALSE;
	}
	
	return read_object_definition( def, e );	
}


// ==============================  SAVE TAG DATA (WITH ID) ========================================
bool save_object_definition( object_definition* def, tag id )
{
	tag_entry* e;
	
	assert( def );
	
	e = get_entry( 'obje', id );
	if( 0 == e ) {
		return FALSE;
	}

	return save_object_definition( def, e );
}


// ==============================  DISPATCH  ========================================
BEGINDISPATCH(TobjeEditForm,TTagEditForm)
	DISPATCHTABLE(KXGControlClick,TobjeEditForm::DoControlClick)
ENDDISPATCH


TobjeEditForm::TobjeEditForm( struct tag_entry *e ) : TTagEditForm( e )
{
}

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

}


// ==============================  INPUT HANDLING  ========================================
static long ModifiersDlogProc( XGDialog *dlog, void *data, long msg, long arg, void *parg )
{
	short_fixed *modifiers = (short_fixed *)data;
	int ii;
	
	switch( msg )
	{
		case KXGDialogMessage:
		{
			switch( arg )
			{
				case KXGDMInitDialog:
				{
					for( ii = 0; ii < NUMBER_OF_EFFECT_MODIFIERS; ii++ )
						SetShortFixed( dlog, 101 + ii, modifiers[ii] );
					
					return 0;
				}
				
				default:
					break;
			}
		}
		case KXGControlClick:
		{
			switch( arg )
			{
				case 1001: // ok
				{
					for( ii = 0; ii < NUMBER_OF_EFFECT_MODIFIERS; ii++ )
						modifiers[ii] = GetShortFixed( dlog, 101 + ii );
				
					dlog->EndDialog( 1 );
					return 0;
				}
				case 1002: // cancel
				{
					dlog->EndDialog( 0 );
					return 0;
				}
				
				default:
					break;
			}
		}
		
		default:
			break;
	}
	
	return -1;
}


long TobjeEditForm::DoControlClick( long arg, void *ptr )
{
#ifdef __MWERKS__
	#pragma unused(ptr)
#endif

	bool ok;

	switch( arg )
	{
		case 11613: // effect modifiers
			short_fixed modifiers[MAXIMUM_NUMBER_OF_EFFECT_MODIFIERS];
			
			memcpy( modifiers, def.effect_modifiers, sizeof(modifiers) );
			
			ok = XGDialog::ModalDialog( KWindowObjectEffectModifiers, ModifiersDlogProc, modifiers );
			if( ok )
				memcpy( def.effect_modifiers, modifiers, sizeof(def.effect_modifiers) );
		break;
		
		default:
			return -1;
	}
	
	return 0;
}

		
// ========================================  SAVE TO TAG  ==================================================
void TobjeEditForm::CommitToTag()
{
	GetValues();
	save_object_definition( &def, fEntry );
}


// ========================================  RELOAD TAG  ==================================================
void TobjeEditForm::ReloadTag()
{
	read_object_definition( &def, fEntry );
	SetValues();
}


// ========================================  TAG NEEDS UPDATING  ==================================================
bool TobjeEditForm::NeedCommit()
{
	GetValues();
	return tag_data_needs_update( "obje", fEntry, &def, SIZEOF_STRUCT_OBJECT_DEFINITION, 1, object_definition_byte_swapping_data);
}

		
// ========================================  SET INTERFACE VALUES  ==================================================
void TobjeEditForm::SetValues()
{
	SetShortWorldDistance( 11601, def.gravity );
	SetShortWorldDistance( 11602, def.terminal_velocity );
	SetShortFixed( 11603, def.elasticity );
	
	SetShortFixed( 11604, def.maximum_vitality );
	SetShortFixed( 11605, get_upper_bound( def.maximum_vitality, def.maximum_vitality_delta ) );
	SetShortFixed( 11606, def.scale_lower_bound );
	SetShortFixed( 11607, get_upper_bound( def.scale_lower_bound, def.scale_delta ) );
	SetShortFixed( 11608, def.minimum_damage );

	if(def.flags&_draw_selection_box_flag ) {
		SetFlag( 11609, TRUE );
	} else {
		SetFlag( 11609, FALSE );
	}
	if(def.flags&_draw_vitality_box_flag ) {
		SetFlag( 11610, TRUE );
	} else {
		SetFlag( 11610, FALSE );
	}
	if(def.flags&_maintains_constant_height_above_ground_flag ) {
		SetFlag( 11611, TRUE );
	} else {
		SetFlag( 11611, FALSE );
	}
	if(def.flags&_ignore_model_and_object_collisions_flag ) {
		SetFlag( 11612, TRUE );
	} else {
		SetFlag( 11612, FALSE );
	}
}


// ========================================  GET INTERFACE VALUES  ==================================================
void TobjeEditForm::GetValues()
{
	def.gravity = GetShortWorldDistance( 11601 );
	def.terminal_velocity = GetShortWorldDistance( 11602 );
	def.elasticity = GetShortFixed( 11603 );
	def.maximum_vitality = GetShortFixed( 11604 );
	def.maximum_vitality_delta = get_delta( GetShortFixed( 11604 ), GetShortFixed( 11605 ) );
	def.scale_lower_bound = GetShortFixed( 11606 );
	def.scale_delta = get_delta( GetShortFixed( 11606 ), GetShortFixed( 11607 ) );
	def.minimum_damage = GetShortFixed( 11608 );

	def.flags = 0;
	if(GetFlag( 11609 )) def.flags |= _draw_selection_box_flag;
	if(GetFlag( 11610 )) def.flags |= _draw_vitality_box_flag;
	if(GetFlag( 11611 )) def.flags |= _maintains_constant_height_above_ground_flag;
	if(GetFlag( 11612 )) def.flags |= _ignore_model_and_object_collisions_flag;
	
}

bool replace_object_data( tag_entry *te, vengeance_script_obje *obje )
{
	object_definition object;
	
	if( read_object_definition( &object, te ) )
	{
		object.maximum_vitality = obje->maximum_vitality;
		object.maximum_vitality_delta = obje->maximum_vitality_delta;
		object.scale_lower_bound = obje->scale_lower_bound;
		object.scale_delta = obje->scale_delta;
		object.minimum_damage = obje->minimum_damage;
		memcpy( &object.effect_modifiers, &obje->effect_modifiers, MAXIMUM_NUMBER_OF_EFFECT_MODIFIERS * sizeof(short_fixed) );

		object.flags &= obje->flag_mask;
		object.flags |= obje->flags;
	}
	
	return save_object_definition( &object, te );
}

bool retrive_object_data( tag_entry *te, vengeance_script_obje *obje )
{
	object_definition object;
	
	if( read_object_definition( &object, te ) )
	{
		obje->maximum_vitality = object.maximum_vitality;
		obje->maximum_vitality_delta = object.maximum_vitality_delta;
		obje->scale_lower_bound = object.scale_lower_bound;
		obje->scale_delta = object.scale_delta;
		obje->minimum_damage = object.minimum_damage;
		memcpy( &obje->effect_modifiers, &object.effect_modifiers, MAXIMUM_NUMBER_OF_EFFECT_MODIFIERS * sizeof(short_fixed) );
		obje->flags = object.flags;
	
		return TRUE;
	}
	
	return FALSE;
}
