/*
    Copyright (C) 2012 Modelon AB

    This program is free software: you can redistribute it and/or modify
    it under the terms of the BSD style license.

     This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    FMILIB_License.txt file for more details.

    You should have received a copy of the FMILIB_License.txt file
    along with this program. If not, contact Modelon AB <http://www.modelon.com>.
*/

#ifndef JM_PORTABILITY_H_
#define JM_PORTABILITY_H_
#include <fmilib_config.h>
#include "jm_callbacks.h"

/* Include platform dependent headers */
#if defined(_MSC_VER) || defined(WIN32) || defined(__MINGW32__)
#include <windows.h> /* Microsoft Windows API */
#define DLL_HANDLE HANDLE
#else
#define DLL_HANDLE void*
#include <dlfcn.h>  /* Standard POSIX/UNIX API */
#endif

#include "jm_types.h"
/** \file jm_portability.h
	Handling platform specific defines and functions.
*/
/**
	\addtogroup jm_utils
	@{
		\addtogroup jm_portability
	@}
*/
/** \addtogroup jm_portability Handling platform specific defines and functions
@{*/
/** \brief Load a dll/so library into the process and return a handle. */
DLL_HANDLE		jm_portability_load_dll_handle		(const char* dll_file_path);

/** \brief Unload a Dll and release the handle*/
jm_status_enu_t jm_portability_free_dll_handle		(DLL_HANDLE dll_handle);

/** \brief A function pointer as returned when DLL symbol is loaded.*/
#ifdef WIN32
#define jm_dll_function_ptr FARPROC
#else
typedef void* jm_dll_function_ptr; 
#endif

/** \brief Find a function in the Dll and return a function pointer */
jm_status_enu_t jm_portability_load_dll_function	(DLL_HANDLE dll_handle, char* dll_function_name, jm_dll_function_ptr* dll_function_ptrptr);

/** \brief Return error associated with Dll handling */
char* jm_portability_get_last_dll_error	(void);

/** \brief Get current working directory name */
jm_status_enu_t jm_portability_get_current_working_directory(char* buffer, size_t len);

/** \brief Set current working directory*/
jm_status_enu_t jm_portability_set_current_working_directory(const char* cwd);

/** \brief Get system-wide temporary directory */
const char* jm_get_system_temp_dir();

/** 
	\brief Create a unique file name 
	\param tmplt File name template ending with XXXXXX.
	\return A pointer to the modified template. The function returns NULL if 
	template is badly formed or no more unique names can be created from the given template.
*/
char* jm_mktemp(char* tmplt);


/** 
	\brief Get absolute path to an existing directory
	\param cb - callbacks for memory allocation and logging. Default callbacks are used if this parameter is NULL.
	\param dir - path to a directory (relative or absolute).
	\param outPath - buffer for storing the directory
	\param len - of the buffer (if size is larger than FILENAME_MAX + 1 then the path will always fit in)
	\return Pointer to outPath on success, 0 - on error in which case a message is send to the logger.	
*/
char* jm_get_dir_abspath(jm_callbacks* cb, const char* dir, char* outPath, size_t len);

/** 
	\brief Create a unique temporary directory
	\param cb - callbacks for memory allocation and logging. Default callbacks are used if this parameter is NULL.
	\param systemTempDir - directory where the temp dir should be located both absolute and relative path are accepted.
				System-wide directory is used if this parameter is NULL.
	\param tempPrefix - File name template prefix used when creating temporaty directories. "jm" is used if this is NULL.
	\return A pointer to the temporary directory name (absolute path, no terminating '/'). Caller is responsible for freeing the memory.
		The function returns NULL if there were errors in which case a message is send to the logger.	
*/
char* jm_mk_temp_dir(jm_callbacks* cb, const char* systemTempDir, const char* tempPrefix);

/** 
	\brief Create a file:// URL from absolute path
	\param cb - callbacks for memory allocation and logging. Default callbacks are used if this parameter is NULL.
	\param absPath - absolute path to be converted into the URL
	\return A pointer to the URL. Caller is responsible for freeing the memory.
		The function returns NULL if there were errors in which case a message is send to the logger.	
*/
char* jm_create_URL_from_abs_path(jm_callbacks* cb, const char* absPath);

/**
	\brief Make a directory.
*/
jm_status_enu_t jm_mkdir(jm_callbacks* cb, const char* dir);

/**
\brief Remove directory and all it contents.
*/
jm_status_enu_t jm_rmdir(jm_callbacks* cb, const char* dir);

/**
\brief C89 compatible implementation of C99 vsnprintf. 
*/
FMILIB_EXPORT
int jm_vsnprintf(char * str, size_t size, const char * fmt, va_list al);

/**
\brief C89 compatible implementation of C99 snprintf. 
*/
FMILIB_EXPORT
int jm_snprintf(char * str, size_t size, const char * fmt, ...);

#ifdef HAVE_VA_COPY
#define JM_VA_COPY va_copy
#elif defined(HAVE___VA_COPY)
#define JM_VA_COPY __va_copy
#elif defined(WIN32)
#define JM_VA_COPY(dest,src) dest=src
#endif

/*@}*/
#endif /* End of header file JM_PORTABILITY_H_ */
