/*************************************************************************
	File:	wave_plugin.c

	FormZ data model translator sample.  Imports and exports Wavefront OBJ files.

	COPYRIGHT (C) 2001.  All Rights Reserved.
	auto*des*sys, Inc., Columbus, Ohio, USA.
*************************************************************************/

#include "wave_prvt.h"
#define FZ_BONZAI_AWARE
/* This include file must be included in only the plugins source file which contains 
	the implementation of fz_plugin_entry */
#include "fz_plugin_glue_api.h"



	/* application provided function sets to hold on to */
const fzpl_fset_glue_fset	*_fset_glue = NULL;
fz_ffmt_fset					_ffmt_funcs;
fz_ffmt_data_model_fset		_ffmt_3d_funcs;
fz_math_fset					_math_funcs;
fz_model_fset					_model_funcs;
fz_objt_attr_fset				_objt_attr_funcs;
fz_ncrv_fset					_ncrv_funcs;
fz_nsrf_fset					_nsrf_funcs;
fz_lite_fset					_lite_funcs;
fz_proj_fset					_proj_funcs;
fz_wind_fset					_wind_funcs;
fz_layr_fset					_layr_funcs;
fz_grup_fset					_grup_funcs;
fz_rmtl_fset					_rmtl_funcs;
fz_type_fset					_type_funcs;
fz_iost_fset					_iost_funcs;
fz_syst_fset					_syst_funcs;
fz_fuim_fset					_fuim_funcs;
fz_fzrt_mem_fset				_fzrt_mem_funcs;
fz_fzrt_file_fset				_fzrt_file_funcs;
fz_fzrt_base_fset				_fzrt_base_funcs;
fzpl_plugin_query_fset		_plugin_query_funcs;

	/* plugin's runtime id */
fzrt_unsigned_int					_wave_plugin_runtime_id = FZ_FFMT_NONE;

	/* translator's format reference id */
fz_ffmt_ref_td					_wave_ref = -1;

	/* translator's resource file id */
fzrt_fzr_ref_td					_fz_rsrc_ref = -1;
	
	/* export custom options */
fzrt_int							_write_flags = 0;

	/* import custom options */
fzrt_int							_read_flags = 0;


/************************************************************************
	Acquires all application provided function sets.
*************************************************************************/
static fzrt_error_td wave_acquire_fsets ( void )
{
	fzrt_error_td err;

	err = _fset_glue->fzpl_fset_acquire( FZ_FFMT_FSET_TYPE, FZ_FFMT_FSET_VERSION, FZRT_UUID_NULL,
								 FZPL_TYPE_STRING(fz_ffmt_fset), sizeof(_ffmt_funcs),
								 (fzpl_fset_td *)&_ffmt_funcs );
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_FFMT_DATA_MODEL_FSET_TYPE, FZ_FFMT_DATA_MODEL_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_ffmt_data_model_fset), sizeof(_ffmt_3d_funcs),
									 (fzpl_fset_td *)&_ffmt_3d_funcs );
	}
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_MATH_FSET_TYPE, FZ_MATH_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_math_fset), sizeof(_math_funcs),
									 (fzpl_fset_td *)&_math_funcs );
	}
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_PROJ_FSET_TYPE, FZ_PROJ_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_proj_fset), sizeof(_proj_funcs),
									 (fzpl_fset_td *)&_proj_funcs );
	}
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_WIND_FSET_TYPE, FZ_WIND_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_wind_fset), sizeof(_wind_funcs),
									 (fzpl_fset_td *)&_wind_funcs );
	}
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_LAYR_FSET_TYPE, FZ_LAYR_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_layr_fset), sizeof(_layr_funcs),
									 (fzpl_fset_td *)&_layr_funcs );
	}
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_MODEL_FSET_TYPE, FZ_MODEL_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_model_fset), sizeof(_model_funcs),
									 (fzpl_fset_td *)&_model_funcs );
	}
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_OBJT_ATTR_FSET_TYPE, FZ_OBJT_ATTR_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_objt_attr_fset), sizeof(_objt_attr_funcs),
									 (fzpl_fset_td *)&_objt_attr_funcs );
	}
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_NCRV_FSET_TYPE, FZ_NCRV_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_ncrv_fset), sizeof(_ncrv_funcs),
									 (fzpl_fset_td *)&_ncrv_funcs );
	}
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_NSRF_FSET_TYPE, FZ_NSRF_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_nsrf_fset), sizeof(_nsrf_funcs),
									 (fzpl_fset_td *)&_nsrf_funcs );
	}
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_LITE_FSET_TYPE, FZ_LITE_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_lite_fset), sizeof(_lite_funcs),
									 (fzpl_fset_td *)&_lite_funcs );
	}

	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_TYPE_FSET_TYPE, FZ_TYPE_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_type_fset), sizeof(_type_funcs),
									 (fzpl_fset_td *)&_type_funcs );
	}

	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_GRUP_FSET_TYPE, FZ_GRUP_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_grup_fset), sizeof(_grup_funcs),
									 (fzpl_fset_td *)&_grup_funcs );
	}

	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_RMTL_FSET_TYPE, FZ_RMTL_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_rmtl_fset), sizeof(_rmtl_funcs),
									 (fzpl_fset_td *)&_rmtl_funcs );
	}

	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_IOST_FSET_TYPE, FZ_IOST_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_iost_fset), sizeof(_iost_funcs),
									 (fzpl_fset_td *)&_iost_funcs );
	}

	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_FUIM_FSET_TYPE, FZ_FUIM_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_fuim_fset), sizeof(_fuim_funcs),
									 (fzpl_fset_td *)&_fuim_funcs );
	}

	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_FUIM_FSET_TYPE, FZ_FUIM_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_fuim_fset), sizeof(_fuim_funcs),
									 (fzpl_fset_td *)&_fuim_funcs );
	}
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_FZRT_MEM_FSET_TYPE, FZ_FZRT_MEM_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_fzrt_mem_fset), sizeof(_fzrt_mem_funcs),
									 (fzpl_fset_td *)&_fzrt_mem_funcs );
	}
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_FZRT_FILE_FSET_TYPE, FZ_FZRT_FILE_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_fzrt_file_fset), sizeof(_fzrt_file_funcs),
									 (fzpl_fset_td *)&_fzrt_file_funcs );
	}
	
	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_FZRT_BASE_FSET_TYPE, FZ_FZRT_BASE_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_fzrt_base_fset), sizeof(_fzrt_base_funcs),
									 (fzpl_fset_td *)&_fzrt_base_funcs );
	}

	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZ_SYST_FSET_TYPE, FZ_SYST_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_syst_fset), sizeof(_syst_funcs),
									 (fzpl_fset_td *)&_syst_funcs );
	}

	if(err == FZRT_NOERR)
	{
		err = _fset_glue->fzpl_fset_acquire( FZPL_PLUGIN_QUERY_FSET_TYPE, FZPL_PLUGIN_QUERY_FSET_VERSION, FZRT_UUID_NULL,
									FZPL_TYPE_STRING(fzpl_plugin_query_fset), sizeof(_plugin_query_funcs),
									(fzpl_fset_td *)&_plugin_query_funcs);
	}


	
	return err;
}

/************************************************************************
	Releases all application provided function sets.
*************************************************************************/
static void wave_release_fsets ( void )
{
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_plugin_query_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_syst_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_fuim_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_fzrt_base_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_fzrt_file_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_fzrt_mem_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_iost_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_rmtl_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_grup_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_type_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_lite_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_ncrv_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_nsrf_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_objt_attr_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_model_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_layr_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_wind_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_proj_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_math_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_ffmt_3d_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_ffmt_funcs);
}


/************************************************************************
	Fills the function set structure with the file translator info
	callback functions.
*************************************************************************/
static fzrt_error_td wave_translator_info_get_fset ( const fzpl_fset_def_ptr fset_def, fzpl_fset_td * const fset )
{
	fzrt_error_td					err = FZRT_NOERR;
	fz_ffmt_cbak_info_fset		*info_struct;

	if ( fset_def != NULL && fset != NULL )
	{
			/* Check the version and size of the function set structure */
		_fset_glue->fzpl_fset_def_check ( fset_def, FZ_FFMT_CBAK_INFO_FSET_VERSION, FZPL_TYPE_STRING(fz_ffmt_cbak_info_fset), sizeof ( fz_ffmt_cbak_info_fset ), FZPL_VERSION_OP_NEWER );
		if ( err == FZRT_NOERR )
		{
			info_struct = (fz_ffmt_cbak_info_fset *)fset;

				/* Assign functions to the function set. */
			info_struct->fz_ffmt_cbak_name			= wave_get_name;
			info_struct->fz_ffmt_cbak_uuid			= wave_get_id;
			info_struct->fz_ffmt_cbak_info			= wave_get_info;
			info_struct->fz_ffmt_cbak_ftype			= wave_get_ftype;
			info_struct->fz_ffmt_cbak_icon_rsrc		= wave_get_icon;
			info_struct->fz_ffmt_cbak_icon_file		= NULL;
			info_struct->fz_ffmt_cbak_opts_io		= wave_opts_io;
			info_struct->fz_ffmt_cbak_is_file		= wave_is_wave;
		}
	}
	else
		err =  _fzrt_base_funcs.fzrt_error_set ( FZRT_BAD_PARAM_ERROR, FZRT_ERROR_SEVERITY_ERROR, FZRT_ERROR_CONTEXT_FZRT, 0 );

	return err;
}

/************************************************************************
	Fills the function set structure with the data model file translator
	callback functions.
*************************************************************************/
static fzrt_error_td wave_get_data_model_fset ( const fzpl_fset_def_ptr fset_def, fzpl_fset_td * const fset )
{
	fzrt_error_td					err = FZRT_NOERR;
	fz_ffmt_cbak_data_model_fset	*dm_struct;

	if ( fset_def != NULL && fset != NULL )
	{
			/* Check the version and size of the function set structure */
		_fset_glue->fzpl_fset_def_check ( fset_def, FZ_FFMT_CBAK_DATA_MODEL_FSET_VERSION, FZPL_TYPE_STRING(fz_ffmt_cbak_data_model_fset), sizeof ( fz_ffmt_cbak_data_model_fset ), FZPL_VERSION_OP_NEWER );
		if ( err == FZRT_NOERR )
		{
			dm_struct = (fz_ffmt_cbak_data_model_fset *)fset;

				/* Assign functions to the function set. */
			dm_struct->fz_ffmt_cbak_data_model_tmap_list				= wave_2d_tmap_list;

			dm_struct->fz_ffmt_cbak_data_model_read						= wave_read;
			dm_struct->fz_ffmt_cbak_data_model_read_dlog_cust			= wave_in_dlog_cust_func;
			dm_struct->fz_ffmt_cbak_data_model_read_predloginit			= NULL;
			dm_struct->fz_ffmt_cbak_data_model_read_opts_default		= wave_read_opts_default;
			dm_struct->fz_ffmt_cbak_data_model_read_opts_flags			= wave_read_opts_get_flags;

			dm_struct->fz_ffmt_cbak_data_model_write_begin				= wave_write_begin;
			dm_struct->fz_ffmt_cbak_data_model_write_end				= wave_write_end;
			dm_struct->fz_ffmt_cbak_data_model_write_grup_begin		= wave_write_group_begin;
			dm_struct->fz_ffmt_cbak_data_model_write_grup_end			= wave_write_group_end;
			dm_struct->fz_ffmt_cbak_data_model_write_points				= wave_write_points;
			dm_struct->fz_ffmt_cbak_data_model_write_lines				= wave_write_lines;
			dm_struct->fz_ffmt_cbak_data_model_write_polylines			= wave_write_pline;
			dm_struct->fz_ffmt_cbak_data_model_write_faces				= wave_write_faces;
			dm_struct->fz_ffmt_cbak_data_model_write_objt				= wave_write_mesh;
			dm_struct->fz_ffmt_cbak_data_model_write_smod_solid			= NULL;
			dm_struct->fz_ffmt_cbak_data_model_write_smod_trimmed_surf	= wave_write_trimmed;
			dm_struct->fz_ffmt_cbak_data_model_write_can_do_smooth		= wave_can_do_smooth;
			dm_struct->fz_ffmt_cbak_data_model_write_ctrl				= wave_write_ctrl;
			dm_struct->fz_ffmt_cbak_data_model_write_can_do_ctrl		= wave_can_do_ctrl;
			dm_struct->fz_ffmt_cbak_data_model_write_dlog_cust			= wave_out_dlog_cust_func;
			dm_struct->fz_ffmt_cbak_data_model_write_predloginit		= NULL;
			dm_struct->fz_ffmt_cbak_data_model_write_opts_default		= wave_write_opts_default;
			dm_struct->fz_ffmt_cbak_data_model_write_opts_flags			= wave_write_opts_get_flags;
			dm_struct->fz_ffmt_cbak_data_model_write_err_label			= wave_write_err_lable;
			dm_struct->fz_ffmt_cbak_data_model_write_units_conv			= NULL;
			dm_struct->fz_ffmt_cbak_data_model_write_symb_def_start		= NULL;
			dm_struct->fz_ffmt_cbak_data_model_write_symb_def_end		= NULL;
		}
	}
	else
		err = _fzrt_base_funcs.fzrt_error_set ( FZRT_BAD_PARAM_ERROR, FZRT_ERROR_SEVERITY_ERROR, FZRT_ERROR_CONTEXT_FZRT, 0 );

	return err;
}

/************************************************************************
		A first pass check to see if the plugin can be loaded.
		- Checks licensing if needed.
		- Acquires the application defined function sets which are
			needed by the plugin.
		- Verifies that plugin and application are compatible if needed.
		- Loads the plugin's resource file.
*************************************************************************/
static fzrt_error_td wave_check_config ( const fzpl_fset_glue_fset * const fset_glue, const fzpl_host_config_td * const hostConfig )
{
	fzrt_error_td					err = FZRT_NOERR;
	fzrt_floc_ptr					floc;

	_fset_glue = fset_glue;

	/* IF NEEDED : Check the application's api version */

	/*  Make sure required application defined function sets are available */
	/*  Release the function sets at unload. */

	err = wave_acquire_fsets();

	/* IF NEEDED : Check License */

	/* Make sure the plugin's resource file is available and load it */
	if ( err == FZRT_NOERR )
	{
		_fzrt_file_funcs.fzrt_file_floc_init(&floc);
		err = fset_glue->fzpl_plugin_file_get_floc(floc);
		if ( err == FZRT_NOERR )
		{
			err = _fzrt_base_funcs.fzrt_fzr_open(floc, "wave", &_fz_rsrc_ref);
		}
		_fzrt_file_funcs.fzrt_file_floc_finit(&floc);
	}	

	if ( err == FZRT_NOERR )
	{
		wave_release_fsets();
	}

	return err;
}

/************************************************************************
	Registers plugins and their assocoated function sets.
*************************************************************************/
static fzrt_error_td wave_register_plugins ( const fzpl_fset_glue_fset * const fset_glue, const fzpl_host_config_td * const hostConfig )
{
	fzrt_error_td					err = FZRT_NOERR;
	fzrt_int							num_failed = 0;
	char							pname[FZPL_NAME_SIZE];

		/* Make sure the plugin can run. */
	err = wave_check_config ( fset_glue, hostConfig );
	if(err == FZRT_NOERR)
	{
		/* Register the plugin */
		_fzrt_base_funcs.fzrt_fzr_get_string(_fz_rsrc_ref, WAVE_STRINGS, WAVE_NAME_STR, pname);
		err = fset_glue->fzpl_plugin_register( WAVE_PLUGIN_ID, pname, WAVE_PLUGIN_VERSION,
											WAVE_PLUGIN_VENDOR,
											WAVE_PLUGIN_URL,
											FZ_FILE_DATA_EXTS_TYPE, FZ_FILE_DATA_EXTS_VERSION,
											wave_error_str_func, 0, NULL,
											&_wave_plugin_runtime_id);
		if ( err != FZRT_NOERR )
		{
			err = FZRT_NOERR;
			num_failed++;
		}
		else
		{
			/* Add the function sets implemented by the plugin */
			err = fset_glue->fzpl_plugin_add_fset( _wave_plugin_runtime_id, FZ_FFMT_CBAK_INFO_FSET_TYPE,
												FZ_FFMT_CBAK_INFO_FSET_VERSION, FZ_FFMT_CBAK_INFO_FSET_NAME,
												FZPL_TYPE_STRING(fz_ffmt_cbak_info_fset), sizeof ( fz_ffmt_cbak_info_fset ),
												wave_translator_info_get_fset, FALSE);
			if(err == FZRT_NOERR)
			{
				err = fset_glue->fzpl_plugin_add_fset( _wave_plugin_runtime_id, FZ_FFMT_CBAK_DATA_MODEL_FSET_TYPE,
													FZ_FFMT_CBAK_DATA_MODEL_FSET_VERSION, FZ_FFMT_CBAK_DATA_MODEL_FSET_NAME,
													FZPL_TYPE_STRING(fz_ffmt_cbak_data_model_fset), sizeof ( fz_ffmt_cbak_data_model_fset ),
													wave_get_data_model_fset, FALSE);
			}
		}

		/* If registering more than one plugin, and some of the plugins fail to register, return an err with severity
			set to FZRT_ERROR_SEVERITY_WARNING and do not release application implemented function sets.
			If all plugins fail to register return an err with severity set to FZRT_ERROR_SEVERITY_ERROR. and
			release application implemented function sets */
		if ( num_failed == 1 )
		{
			/* Release application implemented function sets */
			wave_release_fsets();
			return ( _fzrt_base_funcs.fzrt_error_set ( FZRT_UNKNOWN_ERROR, FZRT_ERROR_SEVERITY_ERROR, FZRT_ERROR_CONTEXT_FZRT, 0 ) );
		}
		else
			err = FZRT_NOERR;
	}

	return err;
}

/************************************************************************
	Unregisters plugins.
*************************************************************************/
static fzrt_error_td wave_unregister_plugins ( const fzpl_fset_glue_fset * const fset_glue )
{
	fzrt_error_td					err = FZRT_NOERR;

	/* Unregister the plugin */
	err = fset_glue->fzpl_plugin_unregister(_wave_plugin_runtime_id);

	/* Release application implemented function sets */
	wave_release_fsets();

	return err;
}

/************************************************************************
	The main plugin file entry point.  Plugin initialization and uninitialization
		happens via this function.
*************************************************************************/
FZPL_PLUGIN_FUNC(fzrt_error_td) fz_plugin_entry( const fzpl_fset_glue_fset * const fset_glue, fzpl_command_td cmd, const fzpl_host_config_td * const hostConfig )
{
	fzrt_error_td err = FZRT_NOERR;

	switch ( cmd )
	{
		case FZPL_PLUGIN_INITIALIZE:
			err = wave_register_plugins(fset_glue, hostConfig);
		break;
		
		case FZPL_PLUGIN_EXIT:
			err = wave_unregister_plugins(fset_glue);
		break;
	}

	return ( err );
}

