/*
 *  FBCDatabaseConnection.h
 *  FrontBase
 *
 *  Created by Svend Bodilsen on 5/14/10.
 *  Copyright 2010 Frontbase Inc. All rights reserved.
 *
 */
#ifndef FBCDatabaseConnection__H
#define FBCDatabaseConnection__H

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

#include <stdio.h>

#include "FBCMetaData.h"
#include "FBCErrorMetaData.h"
#include "FBCBlobHandle.h"


typedef struct FBCDatabaseClass FBCDatabaseClass;
typedef struct FBCDatabaseConnection FBCDatabaseConnection;

#ifdef __cplusplus
extern "C" {
#endif

// Version info

const char* fbcdcFBCAccessVersion(void);
const char* fbcdcFBCAccessVerboseVersion(void);

// The two possible subclasses

extern const FBCDatabaseClass* FBCServerConnection;
extern const FBCDatabaseClass* FBCFrameworkConnection;

const        FBCDatabaseClass* fbcdcClass ( FBCDatabaseConnection* self );
const        FBCDatabaseClass* fbcmdClass ( const FBCMetaData* self );

void        fbcdcInitializeDocumentRoot(void);
void        fbcdcSetDocumentRoot ( const char* root);
const char* fbcdcDocumentRoot (void);

// Designated initializer.
// The following url syntax is accepted
//     <URL>       :== [<schema>://][<user-part>][<host-name>][:<database-name>][/<path-name>]  |
//                     <database-name>@<host-name>
//     <user-part> :== <user-name>[:[<database-password>:]<user-password>]@
//     
//     <schema>    :== frontbase | file
//     <database-name> :== <name> | <port-number>
//     <path-name>     :== <name> | <path-name>/<name>
//     <port-number>   :== ...  number in the range from 1 to 65565
//     <name>          :== ...  anything which is not a number and does not contain / 

// If the schema part is not provided the form <database-name>@<host-name>  is
// preferred in the case of a confict.
// The passwords defaults to the empty password, and user to _system, and
// hostname to local host. The database-name defaults to the path-name and vice-versa
// The only meaningful hostname in the file schema is localhost.
// If the file schema is used the path-name have preferences and if the frontbase 
// schema is used the database-name have preference
//
// Examples:
//   file:///foo.fb              same as file://localhost/foo.fb
//   file://:foo                 same as file://localhost/foo.fb
//   frontbase://i8.local/foo.fb same as frontbase://i8.local:foo.fb 
//   foo@i8.local                same as frontbase://i8.local:foo.fb
//
// Please note that the path part is relative to the document root, which may be set by the
// fbcdcSetDocumentRoot, to reference current working directory (cwd) use ./ to refernce an
// absolute path srart with /:
//
//          file://localhost/foo.fb          - relative to document root
//          file://localhost/./foo.fb        - relative to cwd
//          file://localhost//foo.fb         - absolute path
//
// A few strange looking urls
//          file:////foo.fb                  - absolute path on localhost
//          file:///./foo.fb                 - relative to cwd on localhost
//

int fbcdcParseURL ( const char* url, int* isFile, char** hostName, char** databaseName, char** path, char** databasePassword, char** userName, char** password );

void   fbcdcSetConnectTimeout ( double timeout );
double fbcdcConnectTimeout    ( void );
   
FBCMetaData* fbcdcConnectToURL
( const char* url, 
  const char* defaultDatabasePassword,
  const char* defaultUser,
  const char* defaultPassword,
  const char* defaultSessionId
);

typedef unsigned int (*FBCDInputCallback) (void* context, void* buffer, unsigned int length );
void fbcdcSetInputCallback ( FBCDatabaseConnection* self, void* context, FBCDInputCallback callback);

void                   fbcdcShutdown     ( FBCDatabaseConnection* self );
void                   fbcdcClose        ( FBCDatabaseConnection* self );
void                   fbcdcRelease      ( FBCDatabaseConnection* self );
FBCDatabaseConnection* fbcdcRetain       ( FBCDatabaseConnection* self );

const char* fbcdcURL           ( FBCDatabaseConnection* self );
const char* fbcdcDatabaseName  ( FBCDatabaseConnection* self );
const char* fbcdcHostName      ( FBCDatabaseConnection* self );
const char* fbcdcUserName      ( FBCDatabaseConnection* self );
const char* fbcdcPathName      ( FBCDatabaseConnection* self );
const char* fbcdcTimeZoneName  ( FBCDatabaseConnection* self );
      char* fbcdcTimeToAscii   ( FBCDatabaseConnection* self, double time,                unsigned int precision, char* buffer, unsigned int length );
      char* fbcdcTimeToAsciiTZ ( FBCDatabaseConnection* self, double time, int gmtOffset, unsigned int precision, char* buffer, unsigned int length );

void         fbcdcSetSessionID        ( FBCDatabaseConnection* self, const char* anID );
FBCMetaData* fbcdcSetDatabasePassword ( FBCDatabaseConnection* self, const char* newPassword );
FBCMetaData* fbcdcSetPasswordForUser  ( FBCDatabaseConnection* self, const char* userName, const char* newPassword, const char* oldPassword );
int          fbcdcConnected           ( FBCDatabaseConnection* self );
const char*  fbcdcSessionID           ( FBCDatabaseConnection* self );
unsigned int fbcdcBatchMaxRowCount    ( FBCDatabaseConnection* self );
void         fbcdcSetBatchMaxRowCount ( FBCDatabaseConnection* self, unsigned int batchMaxRowCount );

#define FBCDCFetch  1
#define FBCDCCommit 2
FBCMetaData* fbcdcExecuteSQL(FBCDatabaseConnection* self, const char* sql, unsigned int length, unsigned int flags);

FBCErrorMetaData* fbcdcErrorMetaData ( FBCDatabaseConnection* self, FBCMetaData* meta);

FBCDatabaseConnection* fbcmdDatabaseConnection ( const FBCMetaData* self );

FBCDatabaseConnection* fbcdcConnectToDatabaseRM(const char* dbName, const char* hostName, const char* password, const char** errorMsg);
FBCDatabaseConnection* fbcdcConnectToDatabase(const char* dbName, const char* hostName, const char* password);
FBCDatabaseConnection* fbcdcConnectToDatabaseOnThisHostRM(const char* dbName, const char* password, const char** errorMsg);
FBCDatabaseConnection* fbcdcConnectToDatabaseOnThisHost(const char* dbName, const char* password);
FBCDatabaseConnection* fbcdcConnectToDatabaseUsingPortRM(const char* hostName, unsigned portNumber, const char* password, const char** errorMsg);
FBCDatabaseConnection* fbcdcConnectToDatabaseUsingPort(const char* hostName, unsigned portNumber, const char* password);

FBCDatabaseConnection* fbcdcConnectToPathRM (const char* databaseName, const char* pathName, const char* password, const char** errorMsg);

const char* fbcdcClassErrorMessage(void);

FBCMetaData* fbcdcCreateSession         ( FBCDatabaseConnection* self, const char* sessionId, const char* sessionUser, const char* password, const char* systemUser );
FBCMetaData* fbcdcSetSessionUser        ( FBCDatabaseConnection* self, const char* sessionUser, const char* password, const char* systemUser );
FBCMetaData* fbcdcDisconnect            ( FBCDatabaseConnection* self, const char* sessionID );
FBCMetaData* fbcdcDisconnectAll         ( FBCDatabaseConnection* self );
FBCMetaData* fbcdcDisconnectCurrent     ( FBCDatabaseConnection* self );
FBCMetaData* fbcdcDisconnectDefault     ( FBCDatabaseConnection* self);
FBCMetaData* fbcdcSetConnection         ( FBCDatabaseConnection* self, const char* sessionID );
FBCMetaData* fbcdcSetConnectionToDefault( FBCDatabaseConnection* self );



typedef enum { FBCDCStop = 0, FBCDCExit = 1 } FBCDCStopOptions;
FBCMetaData* fbcdcStopDatabaseO (FBCDatabaseConnection* self, FBCDCStopOptions options);
FBCMetaData* fbcdcStopDatabase  ( FBCDatabaseConnection* self ); // exit immediat

int fbcdcSetRollbackAfterError ( FBCDatabaseConnection* self, int flag );

void fbcdcSeterrorsFromFBExec ( FBCDatabaseConnection* self, int flag );
int fbcdcGeterrorsFromFBExec  ( FBCDatabaseConnection* self );

FBCMetaData* fbcdcExecuteDirectSQL (FBCDatabaseConnection* self, char* sql);
FBCMetaData* fbcdcExecuteDirectSQLWithLength( FBCDatabaseConnection* self, const char* sql, unsigned int length);
FBCMetaData* fbcdcExecuteDirectSQLWithFetch( FBCDatabaseConnection* self, const char* sql);
FBCMetaData* fbcdcExecuteDirectSQLWithFetchAndAutoCommit(FBCDatabaseConnection* self, const char* sql);
FBCMetaData* fbcdcExecuteDirectSQLWithFetchAndCommit(FBCDatabaseConnection* self, const char* sql);
FBCMetaData* fbcdcExecuteDirectSQLWithLengthFetchAndCommit(FBCDatabaseConnection* self, const char* sql, unsigned int length);

FBCBlobHandle* fbcdcWriteBLOB(FBCDatabaseConnection* self, const void *blobData, unsigned int blobDataLength);
FBCMetaData*   fbcdcWriteBLOBFromFile ( FBCDatabaseConnection* self, const char* fileName);
FBCMetaData*   fbcdcReadBLOBToFile ( FBCDatabaseConnection* self, FBCBlobHandle* blobHandle, const char* fileName);

//FBCBlobHandle* fbcdcWriteBLOBFromFILE(FBCDatabaseConnection* self, FILE* f, unsigned int);

void *fbcdcReadBLOB(FBCDatabaseConnection* self, FBCBlobHandle *blobHandle);
void *fbcdcReadBLOBChunk(FBCDatabaseConnection* self, FBCBlobHandle *blobHandle, unsigned int offset, unsigned int *chunkSize, void *chunkBuffer);

FBCBlobHandle *fbcdcWriteCLOB(FBCDatabaseConnection* self, const char* aString);
FBCBlobHandle *fbcdcWriteCLOBWithLength(FBCDatabaseConnection* self, const char* aString, unsigned int clobDataLength);

char*          fbcdcReadCLOB(FBCDatabaseConnection* self, FBCBlobHandle *blobHandle);
FBCBlobHandle *fbcdcWriteCHARACTERWithLength(FBCDatabaseConnection* self, const char* aString, unsigned int strLen);
FBCBlobHandle *fbcdcWriteCHARACTER(FBCDatabaseConnection* self, const char* aString);

void  fbcdcReleaseLOB ( void* address );
void* fbcdcRetainLOB  ( void* address );

const char*  fbcdcErrorMessage(FBCDatabaseConnection* self);
FBCMetaData* fbcdcCommit(FBCDatabaseConnection* self);
FBCMetaData* fbcdcRollback(FBCDatabaseConnection* self);
FBCMetaData* fbcdcStopAgent(FBCDatabaseConnection*self, const char* agentID);
FBCMetaData* fbcdcStopAgentsBusyCondition(FBCDatabaseConnection*self, const char* agentID);
FBCMetaData* fbcdcGetDatabaseLogTail(FBCDatabaseConnection*self);
FBCMetaData* fbcdEnableInterrupts(FBCDatabaseConnection* self);
void         fbcdcInterruptAgent(FBCDatabaseConnection* self);

const char*  fbcdcInputCharacterSet ( FBCDatabaseConnection* self);
void         fbcdcSetInputCharacterSet ( FBCDatabaseConnection* self, const char* name );

const char*  fbcdcOutputCharacterSet(FBCDatabaseConnection* self);

void         fbcdcSetOutputCharacterSet(FBCDatabaseConnection* self, const char* name);

int          fbcdcWriteDataDirect(FBCDatabaseConnection* self, void* data, unsigned int length);
FBCMetaData* fbcdcMetaDataDirect(FBCDatabaseConnection* self);

const char* fbcdcVersion      ( FBCDatabaseConnection* self );
int         fbcdcMajorVersion ( FBCDatabaseConnection* self );
int         fbcdcMinorVersion ( FBCDatabaseConnection* self );

FBCMetaData*       fbcdcSetTransactionVersion ( FBCDatabaseConnection* self, unsigned long long version );
unsigned long long fbcdcTransactionVersion    ( FBCDatabaseConnection* self );

void fbcdcSetFormatResult ( FBCDatabaseConnection* self, int flag);
int  fbcdcFormatResult    ( FBCDatabaseConnection* self);

#ifdef __cplusplus
}
#endif

#endif /* FBCDatabaseConnection__H */
