#ifndef FBCExecHandler__H
#define FBCExecHandler__H

#ifndef FBVersion
#define FBVersion 7
#elif FBVersion != 7
#error "The headers for FBCAccess version have been mixed"
#endif

#include "FBDatabaseDefs.h"
#include "FBCUniqueId.h"
#include "FBCAutoStartInfo.h"
#include "FBDatabaseDefs.h"
/*!
@header FBCExecHandler
 @discussion FBCExecHandler provides a means for connecting to and managing FBExec daemons on a given host.  Using FBCExecHandler, you can retrieve information such as the available databases on a host, their statuses, etc.  You can also create, start, and delete databases.
 */
 

typedef struct FBCExecHandler  FBCExecHandler;
typedef struct FBCDataDaseList FBCDataDaseList;


#ifdef __cplusplus
extern "C" {
#endif

/*!
@enum FBExecClientType
 @discussion The various well known client types which can be registered with FBExec using fbcehHandlerForHostWithClient and friends.
 */


/*!
@function fbcehSetMultiThreaded
 @discussion Setting multithreaded to true will cause new instances of FBCExecHandler to be created for each request to fbcehHandlerForHost (and friends).  Also, no permanent connection will be maintained to the FBExec daemon; rather, connections will be reestablished for each request.
 */
void fbcehSetMultiThreaded(int flag);

/*!
@function fbcehHandlerForHostSingleShot
 @discussion Like fbcehHandlerForHostWithClientRM, except that the caching mechanism (directed by _multiThreaded) is not used
 */
FBCExecHandler* fbcehHandlerForHostSingleShot(const char* hostName, const char** errorMsg);

/*!
@function fbcehHandlerForHostWithClientRM
 @discussion Like fbcehHandlerForHostWithClient, except that *errorMsg identifies the error message if an error occurs.  The caller should not free the error message string.
 */
FBCExecHandler* fbcehHandlerForHostWithClientRM(const char* hostName, FBExecClientType clientType, const char* clientName, unsigned clientID, const char** errorMsg);

/*!
@function fbcehHandlerForHostWithClient
 @discussion Establishes a connection, known as exec handler object, to the FBExec daemon running on the specified host.
 @param hostName Host of the FBExec daemon.
 @param clientType The type of client requesting connection (see FBExecClientType).
 @param clientName Name of the client tool or application (such as "FrontBase Manager").
 @param clientID Identifier for client.
 @result Returns either a connected FBCExecHandler object, or NULL upon error.  In the event of an error, an error message can be retrieved using fbcehClassErrorMessage().
 */
FBCExecHandler* fbcehHandlerForHostWithClient(const char* hostName, FBExecClientType clientType, const char* clientName, unsigned clientID);

int fbcehIsConnected ( FBCExecHandler* self );
int fbcehConnect     ( FBCExecHandler* self );
/*!
@function fbcehHandlerForHostRM
 @discussion Like fbcehHandlerForHost, except that *errorMsg identifies the error message if an error occurs.  The caller should not free the error message string.
 */
FBCExecHandler* fbcehHandlerForHostRM(const char* hostName, FBExecClientType clientType, const char** errorMsg);

/*!
@function fbcehHandlerForHost
 @discussion Convenience for fbcehHandlerForHostWithClient with "any client" and a zero client ID.
 */
FBCExecHandler* fbcehHandlerForHost(const char* hostName, FBExecClientType clientType);

/*!
@function fbcehHandlerForThisHostRM
 @discussion Like fbcehHandlerForThisHost, except that *errorMsg identifies the error message if an error occurs.  The caller should not free the error message string.
 */
FBCExecHandler* fbcehHandlerForThisHostRM(FBExecClientType clientType, const char** errorMsg);

/*!
@function fbcehHandlerForThisHost
 @discussion Convenience for fbcehHandlerForHostWithClient with localhost, "any client" and a zero client ID.
 */
FBCExecHandler* fbcehHandlerForThisHost(FBExecClientType clientType);

/*!
@function fbcehHandlerForHostWithClientPW
 @discussion Similar to fbcehHandlerForHostWithClientRM, but also takes a clear text password as the FBExec password.
 */
FBCExecHandler* fbcehHandlerForHostWithClientPW(char* hostName, FBExecClientType clientType, const char* clientName, unsigned clientID, const char* passwd, char** errorMsg);

/*!
@function fbcehHandlerForHostPW
 @discussion Similar to fbcehHandlerForHostRM, but also takes a clear text password as the FBExec password.
 */
FBCExecHandler* fbcehHandlerForHostPW(char* hostName, FBExecClientType clientType, const char* passwd, char** errorMsg);

/*!
@function fbcehHandlerForThisHostPW
 @discussion Similar to fbcehHandlerForThisHostRM, but also takes a clear text password as the FBExec password.
 */
FBCExecHandler* fbcehHandlerForThisHostPW(FBExecClientType clientType, const char* passwd, char** errorMsg);

/*!
@function fbcehHostname
 @discussion Returns the hostname associated with the given exec handler.  Please note that this is the same hostname that was provided to create the exec handler, not a resolved version of the IP address associated with the socket.  Thus, this could return a "hostname" in dotted quad format, such as "127.0.0.1".
 */
const char* fbcehHostname(FBCExecHandler* self);

/*!
@function fbcehVersion
 @discussion Returns the FBExec version, which can be useful when writing tools which must be compatible with several versions of FrontBase.
 @result The returned string should not be freed by the caller.
 */
const char* fbcehVersion(FBCExecHandler* self);

/*!
 @function fbcehClassErrorMessage
 @discussion Returns an error message describing a connection error.
 @result The returned string should not be freed by the caller.
 */
const char* fbcehClassErrorMessage(void);

/*!
@function fbechErrorMessage
 @discussion Backwards compatible version of fbcehErrorMessage().
 */
const char*       fbechErrorMessage(FBCExecHandler* self);
const char* fbcehErrorMessageClear(FBCExecHandler* self);  // Clear the message as well
/*!
@function fbcehErrorMessage
 @discussion Returns an error message to describe a command failure.
 @result The returned string should not be freed by the caller.
 */
const char* fbcehErrorMessage(FBCExecHandler* self);

/*!
@function fbcehDisconnectAll
 @discussion Disconnect all exec handlers.  Most often used when terminating.
 */
void fbcehDisconnectAll(void);

/*!
@function fbcehDisconnect
 @discussion Disconnect the given exec handler.
 */
void fbcehDisconnect(FBCExecHandler* self);

/*!
@function fbcehRelease
 @discussion Releases the resources associated with an FBCExecHandler.
 */
void fbcehRelease(FBCExecHandler* self);

/*!
@function fbcehAvailableDatabases
 @discussion Returns the available databases on the given host.
 @result An FBArray object of the available databases.  When finished, the caller should free this array by calling fbcehReleaseDBNames().
 */
FBCDataDaseList* fbcehAvailableDatabases(FBCExecHandler* self);

/*!
@function fbcehDBNameAtIndex
 @discussion Returns the name of the database at the given index, or NULL if the index is out of bounds.
 @result The returned string should not be freed by the caller.
 */
unsigned int fbcehAvailableDatabasesCount ( FBCDataDaseList* availables);
char*        fbcehDBNameAtIndex           ( FBCDataDaseList* availables, unsigned int index);

/*!
@function fbcehReleaseDBNames
 @discussion Releases the resources associated with the database array returned from fbcehAvailableDatabases().
 */
void fbcehReleaseDBNames(FBCDataDaseList* availables);

/*!
@function fbcehStatusForDatabaseNamed
 @discussion Returns the current status of the given database.  See the enum, FBDatabaseStatus.
 */
FBDatabaseStatus fbcehStatusForDatabaseNamed(FBCExecHandler* self, const char* dbName);

/*!
@function fbcehPortNumberForDatabaseNamed
 @discussion Returns the port number to use for connecting to the given database.
 */
unsigned fbcehPortNumberForDatabaseNamed(FBCExecHandler* self, const char* dbName);

/*!
@function fbcehGetClientID
 @discussion Returns the client ID of the given client.  Returns 0xffffffff upon error.
 */
unsigned fbcehGetClientID(FBCExecHandler* self, const char* clientName);

/*!
@function fbcehGetClientIDTyped
 @discussion Returns the client ID of the given client of the given type.  Returns 0xffffffff upon error.
 */
unsigned fbcehGetClientIDTyped(FBCExecHandler* self, const char* clientName, FBExecClientType type);

// Get the latest string of options the given database has been started with.
// It is up to the caller to copy the returned string before the next call to the
// handler. A return value of NULL means that no options string is available.
/*!
@function fbcehGetOptionsForDatabaseNamed
 @discussion Return the latest string of options which the given database was started with.  NULL will be returned if the options string is not available.  Since the string returned is a shared internal buffer, it should not be freed by the caller, and must be copied before a subsequent call to fbcehGetOptionsForDatabaseNamed() if you wish to retain the original information.
 */
const char* fbcehGetOptionsForDatabaseNamed(FBCExecHandler* self, const char* dbName);

/*!
@function fbcehStartDatabaseNamed
 @discussion Start the given database.
 @result Returns True upon success, False upon failure.
 */
int fbcehStartDatabaseNamed(FBCExecHandler* self, const char* dbName);

/*!
@function fbcehStartDatabaseNamedPW
 @discussion Start the given database after authenticating with FBExec using the provided password.
 @result Returns True upon success, False upon failure.
 */
int fbcehStartDatabaseNamedPW(FBCExecHandler* self, const char* dbName, const char* clearTextPassword);

/*!
@function fbcehStartDatabaseNamedWithOptions
 @discussion Start the given database using the specified startup options.
 @result Returns True upon success, False upon failure.
 */
int fbcehStartDatabaseNamedWithOptions(FBCExecHandler* self, const char* dbName, const char* options);

/*!
@function fbcehStartDatabaseNamedWithOptionsPW
 @discussion Start the given database with the specified startup options after authenticating with FBExec using the provided password.
 @result Returns True upon success, False upon failure.
 */
int fbcehStartDatabaseNamedWithOptionsPW(FBCExecHandler* self, const char* dbName, const char* options, const char* clearTextPassword);

/*!
@function fbcehCreateDatabaseNamed
 @discussion Create a new database.  Note: This method has been deprecated.  Please use fbcehStartDatabaseNamedWithOptions() or similar with the -create option.
 */
int fbcehCreateDatabaseNamed(FBCExecHandler* self, const char* dbName);

/*!
@function fbcehCreateDatabaseNamedPW
 @discussion Create a new database.  Note: This method has been deprecated.  Please use fbcehStartDatabaseNamedWithOptionsPW() or similar with the -create option.
 */
int fbcehCreateDatabaseNamedPW(FBCExecHandler* self, const char* dbName, const char* clearTextPassword);

/*!
@function fbcehCreateDatabaseNamedWithOptions
 @discussion Create a new database.  Note: This method has been deprecated.  Please use fbcehStartDatabaseNamedWithOptionsPW() or similar with the -create option.
 */
int fbcehCreateDatabaseNamedWithOptions(FBCExecHandler* self, const char* dbName, const char* options);

/*!
@function fbcehCreateDatabaseNamedWithOptionsPW
 @discussion Create a new database.  Note: This method has been deprecated.  Please use fbcehStartDatabaseNamedWithOptionsPW() or similar with the -create option.
 */
int fbcehCreateDatabaseNamedWithOptionsPW(FBCExecHandler* self, const char* dbName, const char* options, const char* clearTextPassword);

/*!
@function fbcehDeleteDatabaseNamed
 @discussion Deletes a database.  Removes the physical database file and associated log file.  Requires that the database be stopped.
 @result Returns True upon success, False upon failure.
 */
int fbcehDeleteDatabaseNamed(FBCExecHandler* self, const char* dbName);

/*!
@function fbcehDeleteDatabaseNamedPW
 @discussion Same as fbcehDeleteDatabaseNamed(), but authenticates with FBExec first.
 @result Returns True upon success, False upon failure.
 */
int fbcehDeleteDatabaseNamedPW(FBCExecHandler* self, const char* dbName, const char* clearTextPassword);

/*!
@function fbcehKillDatabaseNamed
 @discussion Kills a running database.
 @result Returns True upon success, False upon failure.
 */
int fbcehKillDatabaseNamed(FBCExecHandler* self, const char* dbName);

/*!
@function fbcehRenameDatabaseNamed
 @discussion Renames the given database file and associated log files.
 @result Returns True upon success, False upon failure.
 */
int fbcehRenameDatabaseNamed(FBCExecHandler* self, const char* oldName, const char* newName);

/*!
@function fbcehRenameDatabaseNamed
 @discussion Same as fbcehRenameDatabaseNamed(), but authenticates with FBExec first.
 @result Returns True upon success, False upon failure.
 */
int fbcehRenameDatabaseNamedPW(FBCExecHandler* self, const char* oldName, const char* newName, const char* clearTextPassword);

/*!
@function fbcehDigestPassword
 @discussion Digests the given username and password into a 16 character hex string.
 @result Returns the digested string.  The caller should not free the returned string, and if it must be used after the next FBCExecHandler call, it should be copied into a separate buffer.
 */
char* fbcehDigestPassword(FBCExecHandler* self, const char* userName, const char* password);

/*!
@function fbcehSQLErrorsText
 @discussion Returns the FBSQLErrors.array file, which is a property list based representation of the error message templates.
 @result The caller should not free the returned property list, and if it must be used after the next FBCExecHandler call, it should be copied into a separate buffer.
 */
const char* fbcehSQLErrorsText(FBCExecHandler* self);

/*!
@function fbcehKeywordsText
 @discussion Returns the Keywords.txt file, which is a list of all keywords recognised by FrontBase.
 @result The caller should not free the returned string, and if it must be used after the next FBCExecHandler call, it should be copied into a separate buffer.
 */
const char* fbcehKeywordsText(FBCExecHandler* self);

/*!
@function fbcehGetAutoStartInfo
 @discussion Returns an FBCAutoStartInfo object representing the list of databases (and their start options) which will be automatically started when the FBExec daemon is started with the -autostart option.
 @result An FBCAutoStartInfo object.  The caller is responsible for releasing this object using fbcaiRelease().
 */
FBCAutoStartInfo* fbcehGetAutoStartInfo(FBCExecHandler* self);

/*!
@function fbcehStartFBAppPW
 @discussion Internal administration API.  Not intended for use by the public.
 */
const char* fbcehStartFBAppPW(FBCExecHandler* self, const char* command, const char* options, const char* argument, const char* fbexecPasswd);

/*!
@function fbcehSetAutoStartInfo
 @discussion Specifies the FBCAutoStartInfo for the associated FBExec daemon.  See fbcehGetAutoStartInfo() and FBCAutoStartInfo.h for more details.
 @result Returns True upon success, False upon failure.
 */
int fbcehSetAutoStartInfo(FBCExecHandler* self, FBCAutoStartInfo* startInfo, const char* fbexecPasswd);

/*!
@function fbcehGetDatabaseLogTail
 @discussion Get the newst entry in the log file for the given database.
 @result The returned log string should not be freed by the caller.
 */
const char* fbcehGetDatabaseLogTail(FBCExecHandler* self, const char* shortDatabaseName);

/*!
@function fbcehGetTransactionVersion
 @discussion Get the transaction version for the named database
 @result The transaction version is returned, -1 when an error occurs
 */
unsigned long long fbcehGetTransactionVersion ( FBCExecHandler* self, const char* name );

/*!
@function fbcehGetClusterDescr
 @discussion Get the ClusterDescr for the named database
 @result The ClusterDescr for the database, NULL when an error occurs
 */
const char* fbcehGetClusterDescr ( FBCExecHandler* self, const char* name );

/*!
@function fbcehGetDatabaseId
 @discussion Get the FSUniqueId for the named database
 @result If the FSUniqueId for the named database may be obtained, it is assigned to 'databaseID'
 */
const char* fbcehGetDatabaseId ( FBCExecHandler* self, const char* name, FBCUniqueId uniqueId);

/*!
@function fbcehSetMemberNames
 @discussion Set the MemberNames part of the ClusterDescr for the named database
 @result "OK" for success, error message otherwise
 */
const char* fbcehSetMemberNames ( FBCExecHandler* self, const char* name, const char* memberNames, const char* execPW );

/*!
@function fbcehSetMajorityStatus
 @discussion Set the Majority part of the ClusterDescr for the named database
 @result "OK" for success, error message otherwise
 */
const char* fbcehSetMajorityStatus ( FBCExecHandler* self, const char* name, int status, const char* execPW );

/*!
@function fbcehRemoveClusterOption
 @discussion Remove "-rcluster" from the options file of the named database
 @result "OK" for success, error message otherwise
 */
const char* fbcehRemoveClusterOption ( FBCExecHandler* self, const char* shortDatabaseName, const char* execPW );

// Optimized one shot 
unsigned fbcehPortNumberForDatabaseOnHostRM (  const char* dbName, const char* hostName,char** msg);

// Enable reception of status broadcast
typedef void (*FBCEHBroadcastCB) ( void* context, FBBroadcastKind kind, const char* uid, const char* host, const char* name, const char* data );
void fbcehSetBroadcastCB ( FBCExecHandler* self, void* context, FBCEHBroadcastCB callBack );

const char* fbcehSetPassword ( FBCExecHandler* self, const char* password );

// Ask for a password when one  needed
typedef const char* (*FBCEHPasswordCB) ( void* context );
void fbcehSetPasswordCB ( FBCExecHandler* self, void* context, FBCEHPasswordCB callBack );

#ifdef __cplusplus
   }
#endif

#endif /* FBCExecHandler__H */

