/*************************************************************************
	File:	tga_plugin.c

	FormZ image bitmap translator sample.  Imports and exports Targa images.

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

#include "tga_prvt.h"

/* 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_image_fset				_ffmt_2d_funcs;
fz_proj_fset					_proj_funcs;
fz_math_fset					_math_funcs;
fz_type_fset					_type_funcs;
fz_iost_fset					_iost_funcs;
fz_fuim_fset					_fuim_funcs;
fz_rndr_mngr_fset				_rndr_funcs;
fz_fzrt_base_fset				_fzrt_base_funcs;
fz_fzrt_mem_fset				_fzrt_mem_funcs;
fz_fzrt_file_fset				_fzrt_file_funcs;
fz_fzrt_graf_fset				_fzrt_graf_funcs;
fzpl_plugin_query_fset		_plugin_query_funcs;

	/* The plugin's runtime id */
fzrt_unsigned_int					_tga_plugin_runtime_id = FZ_FFMT_NONE;
	/* The translator's format reference id */
fz_ffmt_ref_td					_tga_ref = -1;
	/* The plugin's resource file id */
fzrt_fzr_ref_td					_fz_rsrc_ref = -1;
	
	/* The export custom options */
fzrt_int							_write_flags = 0;



/************************************************************************
	Acquires all application provided function sets.
*************************************************************************/
static fzrt_error_td tga_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_IMAGE_FSET_TYPE, FZ_FFMT_IMAGE_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_ffmt_image_fset), sizeof(_ffmt_2d_funcs),
									 (fzpl_fset_td *)&_ffmt_2d_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_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_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_RNDR_MNGR_FSET_TYPE, FZ_RNDR_MNGR_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_rndr_mngr_fset), sizeof(_rndr_funcs),
									 (fzpl_fset_td *)&_rndr_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_FZRT_GRAF_FSET_TYPE, FZ_FZRT_GRAF_FSET_VERSION, FZRT_UUID_NULL,
									 FZPL_TYPE_STRING(fz_fzrt_graf_fset), sizeof(_fzrt_graf_funcs),
									 (fzpl_fset_td *)&_fzrt_graf_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 tga_release_fsets ( void )
{
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_plugin_query_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_fzrt_graf_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 *)&_rndr_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_fuim_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_iost_funcs);
	_fset_glue->fzpl_fset_release((fzpl_fset_td *)&_type_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_2d_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 tga_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 && fset )
	{
			/* 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 )
		{
			info_struct = (fz_ffmt_cbak_info_fset *)fset;

				/* Assign functions to the function set. */
			info_struct->fz_ffmt_cbak_name			= tga_get_name;
			info_struct->fz_ffmt_cbak_uuid			= tga_get_id;
			info_struct->fz_ffmt_cbak_info			= tga_get_info;
			info_struct->fz_ffmt_cbak_ftype			= tga_get_ftype;
			info_struct->fz_ffmt_cbak_icon_rsrc		= tga_get_icon;
			info_struct->fz_ffmt_cbak_icon_file		= NULL;
			info_struct->fz_ffmt_cbak_opts_io		= tga_opts_io;
			info_struct->fz_ffmt_cbak_is_file		= NULL;
		}
	}
	else
	{
		err = _fzrt_base_funcs.fzrt_error_set_with_detail ( FZRT_BAD_PARAM_ERROR, FZRT_ERROR_SEVERITY_ERROR, FZRT_ERROR_CONTEXT_FZRT, 0, 3001 );
	}

	return(err);
}


/************************************************************************
	Fills the function set structure with the image bitmap file translator
	callback functions.
*************************************************************************/
static fzrt_error_td tga_get_image_cbak_fset ( const fzpl_fset_def_ptr fset_def, fzpl_fset_td * const fset )
{
	fzrt_error_td					err = FZRT_NOERR;
	fz_ffmt_cbak_image_fset		*imag_struct;

	if ( fset_def && fset )
	{
			/* Check the version and size of the function set structure */
		_fset_glue->fzpl_fset_def_check ( fset_def, FZ_FFMT_CBAK_IMAGE_FSET_VERSION, FZPL_TYPE_STRING(fz_ffmt_cbak_image_fset), sizeof ( fz_ffmt_cbak_image_fset ), FZPL_VERSION_OP_NEWER );
		if ( !err )
		{
			imag_struct = (fz_ffmt_cbak_image_fset *)fset;

				/* Assign functions to the function set. */
			imag_struct->fz_ffmt_cbak_image_read_dlog_cust					= NULL;
			imag_struct->fz_ffmt_cbak_image_read_predloginit				= NULL;
			imag_struct->fz_ffmt_cbak_image_read_opts_default				= NULL;
			imag_struct->fz_ffmt_cbak_image_read_opts_flags					= tga_read_opts_get_flags;

			imag_struct->fz_ffmt_cbak_image_write_dlog_cust					= tga_dlog_cust_func;
			imag_struct->fz_ffmt_cbak_image_write_predloginit				= NULL;
			imag_struct->fz_ffmt_cbak_image_write_opts_default				= tga_write_opts_default;
			imag_struct->fz_ffmt_cbak_image_write_opts_flags				= tga_write_opts_get_flags;
			
			imag_struct->fz_ffmt_cbak_image_bmap_read_info					= tga_read_info;
			imag_struct->fz_ffmt_cbak_image_bmap_read						= tga_read_image;
			
			imag_struct->fz_ffmt_cbak_image_bmap_write_progress_str			= tga_write_progress_str;
			imag_struct->fz_ffmt_cbak_image_bmap_write_file_begin			= tga_export_init;
			imag_struct->fz_ffmt_cbak_image_bmap_write_image_begin			= tga_out_init_image;
			imag_struct->fz_ffmt_cbak_image_bmap_write_image_scanline_byte	= tga_out_buffer_2_file_image;
			imag_struct->fz_ffmt_cbak_image_bmap_write_image_end			= tga_out_finit_image;
			imag_struct->fz_ffmt_cbak_image_bmap_write_file_end				= tga_export_finit;
			imag_struct->fz_ffmt_cbak_image_bmap_write_err_label			= tga_write_err_lable;
		}
	}
	else
	{
		err = _fzrt_base_funcs.fzrt_error_set_with_detail ( FZRT_BAD_PARAM_ERROR, FZRT_ERROR_SEVERITY_ERROR, FZRT_ERROR_CONTEXT_FZRT, 0, 3001 );
	}

	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 tga_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 version and api version */

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

	err = tga_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);
		{
			err = _fzrt_base_funcs.fzrt_fzr_open(floc, "tga", &_fz_rsrc_ref);
		}
		_fzrt_file_funcs.fzrt_file_floc_finit(&floc);
	}	

	return(err);
}

/************************************************************************
	Registers plugins and their assocoated function sets.
*************************************************************************/
static fzrt_error_td tga_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 = tga_check_config(fset_glue, hostConfig);

	if(err == FZRT_NOERR)
	{
		/* Register the plugin */
		_fzrt_base_funcs.fzrt_fzr_get_string(_fz_rsrc_ref, TGA_STRINGS, TGA_NAME_STR, pname);
		err = fset_glue->fzpl_plugin_register( TGA_PLUGIN_ID, pname, TGA_PLUGIN_VERSION,
											TGA_PLUGIN_VENDOR,
											TGA_PLUGIN_URL,
											FZ_FILE_IMAGE_EXTS_TYPE, FZ_FILE_IMAGE_EXTS_VERSION,
											tga_error_str_func, 0, NULL,
											&_tga_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( _tga_plugin_runtime_id, FZ_FFMT_CBAK_INFO_FSET_TYPE,			/* TAH 11/19/03 begin { */
												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 ),
												tga_translator_info_get_fset, FALSE);
			if(err == FZRT_NOERR)
			{
				err = fset_glue->fzpl_plugin_add_fset( _tga_plugin_runtime_id, FZ_FFMT_CBAK_IMAGE_FSET_TYPE,
													FZ_FFMT_CBAK_IMAGE_FSET_VERSION, FZ_FFMT_CBAK_IMAGE_FSET_NAME,
													FZPL_TYPE_STRING(fz_ffmt_cbak_image_fset), sizeof ( fz_ffmt_cbak_image_fset ),
													tga_get_image_cbak_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 */
			tga_release_fsets();
			err = _fzrt_base_funcs.fzrt_error_set_with_detail ( FZRT_UNKNOWN_ERROR, FZRT_ERROR_SEVERITY_ERROR, FZRT_ERROR_CONTEXT_FZRT, 0, 3002 );
		}
		else
		{
			err = FZRT_NOERR;
		}
	}

	return(err);
}

/************************************************************************
	Unregisters plugins.
*************************************************************************/
static fzrt_error_td tga_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( _tga_plugin_runtime_id );

	/* Release application implemented function sets */
	tga_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 = tga_register_plugins( fset_glue, hostConfig );
		break;
		
		case FZPL_PLUGIN_EXIT:
			err = tga_unregister_plugins( fset_glue );
			break;
			
		default:
			break;
	}

	return(err);
}

