#ifndef	ARCH_H
#define	ARCH_H

#include <../source/TAL/objbase.h>
#include <../source/PAL/oshead.h> /* FIXME */

/*
 * Include arch-independent miscellaneous stuff
 */
#include <../arch/common/c_misc.h>

/*
 * Data types and macros common for all platforms
 */
typedef enum
{
	file_mode_read,
	file_mode_write,
	file_mode_append
}	file_mode_t;

/*
 * open(...) call on directories not supported on all platforms.
 * We limit archFileOpen() fo regular files, block and character
 * devices.
 */
typedef enum
{
	file_type_reg,		/* regular file */
	file_type_blk_dev,	/* block special file */
	file_type_chr_dev,	/* character special file */
	file_type_unknown	/* unknown file type */
}	file_type_t;

/*
 * Include arch-specific config macros and data types.
 */
#if		defined(__UNIX__)
#include <../arch/generic/arch.h>
#elif	defined(__WIN32__)
#include <../arch/win32/arch.h>
#else
#error	"Unknown platform !"
#endif

/*
 * All arguments except those marked as '...ARGNAME..._opt' are mandatory
 * and must NOT be null.
 */
#ifdef __cplusplus
extern "C" {
#endif	/* __cplusplus */
	/*
	 * Time stamp functions (mandatory)
	 */
	void	V_CALL	archDelayExecution(u32_t milliseconds);
	vsize_t	V_CALL	archTickCount(void);
	/*
	 * File I/O (mandatory)
	 */
	vboolean	V_CALL	archFileExists(char *right_slashed_name);
	vboolean	V_CALL	archDeleteFile(char *right_slashed_name);
	vboolean	V_CALL	archMoveFile(char *old_path,char *new_path);
	arch_file_t	V_CALL	archFileOpen(char *right_slashed_name,file_mode_t filemode,file_type_t *ft_ret_opt);
	file_type_t V_CALL	archGetFileType(arch_file_t file);
	vsize_t	V_CALL	archGetFileSize(arch_file_t file);
	vsize_t	V_CALL	archGetFilePointer(arch_file_t file);
	vboolean	V_CALL	archSetFilePointer(arch_file_t file,vsize_t	offset,u32_t whence);
	vboolean 	V_CALL	archFlushFileBuffers(arch_file_t file);
	vsize_t	V_CALL	archFileRead(arch_file_t file,void *buffer,vsize_t len);
	vsize_t	V_CALL	archFileWrite(arch_file_t file,void *buffer,vsize_t len);
	void		V_CALL	archFileClose(arch_file_t file);
	/*
	 * Console I/O (mandatory)
	 */
	arch_file_t	V_CALL	archOpenConsole(file_mode_t filemode);
	/*
	 * FS management (mandatory)
	 */
	vboolean	V_CALL	archDirectoryExists(char *right_slashed_name);
	vboolean	V_CALL	archGetCurrentDirectory(char *right_slashed_dir_ret,u32_t dir_ret_size);
	vboolean	V_CALL	archSetCurrentDirectory(char *right_slashed_new_dir,vboolean *dir_exist_ret_opt);
	vboolean	V_CALL	archMakeDirectory(char *right_slashed_new_dir);
	vboolean	V_CALL	archGetTempDirectory(char *right_slashed_dest,u32_t dest_len);
	vboolean	V_CALL	archFindFirst(char *right_slashed_dir_name,struct arch_dir_s *dir_ret);
	vboolean	V_CALL	archFindNext(struct arch_dir_s *dir);
	void		V_CALL	archFindClose(struct arch_dir_s *dir);
	/*
	 * Misc functions (mandatory)
	 */
	void		V_CALL	archUniqueString(char *buf,vsize_t buffer_size);
	/*
	 * Threading (mandatory). For single-task systems, there must be
	 * at least stubs (for example, archCreateThread() may execute the
	 * passed routine sequentially).
	 */
	vboolean V_CALL archCreateMutex(arch_mutex_p mutex_ret);
	vboolean V_CALL archDestroyMutex(arch_mutex_p mutex);
	vboolean V_CALL archTryLockMutex(arch_mutex_p mutex);
	vboolean V_CALL archLockMutex(arch_mutex_p mutex);
	vboolean V_CALL archUnlockMutex(arch_mutex_p mutex);
	/* TODO */
	
#ifdef	ARCH_MAPPED_IO_SUPPORTED
	/*
	 * Memory-mapped I/O (optional)
	 */

	/*
	 * Mapping length can be 0; in this case 'size'-'start' bytes will be mapped.
	 */
	void_p		V_CALL	archMapRead(arch_file_t file,vsize_t start,
		vsize_t len,struct arch_filemap_s *map_ret);
	/*
	 * Mapping length must be non-0.
	 */
	void_p		V_CALL	archMapReadWrite(arch_file_t file,
		vsize_t start,vsize_t len,struct arch_filemap_s *map_ret);

	void		V_CALL	archUnmap(struct arch_filemap_s *map);
#endif	/* ARCH_MAPPED_IO_SUPPORTED */

#ifdef	ARCH_IPC_SUPPORTED
	/*
	 * Half-duplex named pipes (optional).
	 */
	/* server side */
	vboolean	V_CALL	archInboundPipe(char *name,arch_pipe_p pipe_ret);
	vboolean	V_CALL	archInboundPipeRecv(arch_pipe_p pipe,void_p msg); /* blocking */
	vboolean	V_CALL	archInboundPipeHasData(arch_pipe_p pipe);
	vboolean	V_CALL	archInboundPipeWait(arch_pipe_p pipe,vsize_t timeout_ms);
	/* client side */
	vboolean	V_CALL	archOutboundPipe(char *name,arch_pipe_p pipe_ret);
	vboolean	V_CALL	archOutboundPipeSend(arch_pipe_p pipe,void_p msg);
	/* both for client and server */
	void		V_CALL	archPipeClose(arch_pipe_p pipe);
#endif	/* ARCH_IPC_SUPPORTED */

#ifdef __cplusplus
}
#endif	/* __cplusplus */

#ifdef	ARCH_WINDOWING_SUPPORTED
#include "common/winlib.h"
#endif	/* ARCH_WINDOWING_SUPPORTED */

#endif	/* ARCH_H */
