/*
 * Copyright JaguarDB
 *
 * This file is part of JaguarDB.
 *
 */
#ifndef _jaguar_api_h_
#define _jaguar_api_h_

#include <stdio.h>
#include <string>

#ifdef _WIN32
#ifdef shared_EXPORTS
#define EXP_LIB_API __declspec(dllexport)
#else
#define EXP_LIB_API __declspec(dllimport)
#endif
#else
#define EXP_LIB_API
#endif

class EXP_LIB_API JaguarAPI
{
  public:
  	JaguarAPI( );
	~JaguarAPI();

    // 1: OK; 0: error
	int connect( const char *ipaddress, int port, const char *apikey, const char *dbname );


    // send DML command (not select) to socket to server
    // 1: OK   0: error
    int execute( const char *query ); 
    int execute( const std::string &query ); 

    // send command to socket to server
    // 1: OK   0: error
    int startQuery( const char *query ); 
    int startQuery( const std::string &query ); 
    void endQuery();

    std::string getTenant();
    std::string getApiKey();
    std::string makeApiKey();

    // 0: error or reaching the last record
    // 1: successful and having more records
    int read();
    int fetch();
    int readAll();
    //int reply( bool headerOnly=false );
    //int fetch( bool headerOnly=false );
	// Get all reply in a loop until reply becomes false
	// It drains all sent data from server.
    //int replyAll();
    //int  reconnectflag( int flag = -1 );
	// get session string
	//const char *getSession();

	// get database string
	std::string getDatabase();

	// get type of column
	const char *getColumnType( const char *dbtabcol );

    std::string getFileColumnOfVector(const char *dbtabveccol );
    std::string getTextColumnOfVector(const char *dbtabveccol );
    std::string getFirstZuidCol( const char *dbobj );

    // get error string from row
    std::string error( ); 
    
    // row hasError?
    // 1: yes  0: no
    int hasError( );

    // get n-th column in the row  1--N
    // NULL if not found; malloced char* if found, must be freed later
    const char *getNthValue( int nth );

    // returns a pointer to char string as value for name
    // The buffer needs to be freed after use
    std::string getValue( const char *name );
    double      getDoubleValue(const char *name, bool &found);
    long        getLongValue(const char *name, bool &found);

    
    std::string getMessage( ); 
    unsigned long getMessageLen();


	// return data string in json format
	// caller should NOT free the pointer
	std::string json( );
    const char *jsonStr();

	// return last zuid
	// caller should NOT free the pointer
	std::string getLastZuid();

    bool isDisconnected();
    int  reconnect();

    // returns a pointer to char string as value for name in GeoJson
    // The buffer cannot be freed after use
    const char *getAllByName( const char *name );

    // get n-th value (GeoJson) 1--N in GeoJson
    // NULL if not found; malloced char* if found
    // The buffer cannot be freed after use
    const char *getAllByIndex( int nth );

    // returns a pointer to char string as value for name in GeoJson
    // The buffer cannot be freed after use
    const char *getAll();

    // client receives a row
    int printRow();

    // print all geojson data
	void printAll();
	void close();


	int   getColumnCount();
	char *getCatalogName( int col );
	char *getColumnClassName( int col );
	int  getColumnDisplaySize( int col );
	char *getColumnLabel( int col );
	char *getColumnName( int col );
	int  getColumnType( int col );
	char *getColumnTypeName( int col );
	int  getScale( int col );
	char *getSchemaName( int col );
	char *getTableName( int col );
	bool isAutoIncrement( int col );
	bool isCaseSensitive( int col );
	bool isCurrency( int col );
	bool isDefinitelyWritable( int col );
	int  isNullable( int col );
	bool isReadOnly( int col );
	bool isSearchable( int col );
	bool isSigned( int col );
	//const char *getHost();
	//bool  allSocketsBad();
	void  setDatcType( int srcType, int destType );
	void  setRedirectSock( void *psockarr );
	int   datcDestType();
	int   datcSrcType();
	void  setDebug( bool flag );
	long  getQueryCount();

    //////////////////////////// encrypt/decrypt methods ///////////////////////////////////////////////////////
    //  Useful if data is encrypted and decrypted

    // create an encryption key and save it into file fpath
    // If successfully created, return the key. Otherwise, return empty string
    // Check the permission of fpath if failed.
    static std::string createEncryptionKey(const char *fpath);

    // return 0 for success; < 0 for error
    int    setDefaultEncryptionKey(const char *fpath);

    // return the encryption key string from a file storing the key
    static std::string readEncryptionKey(const char *fpath);

    // encrypt plaintext with default key into base64Encoded text
    void   encryptWithDefaultKey(const std::string &plaintext, std::string &base64Encoded );

    // decrypt with the default key
    void   decryptWithDefaultKey(const std::string &base64ivciphertext, std::string &plaintext );

    // encrypt plaintext with a given key into base64Encoded text
    static void   encryptWithGivenKey(const std::string &plaintext, const std::string &base64Key, std::string &base64EncodedResult );

    // decrypt base64Encoded text with a key into plaintextResult
    static void   decryptWithGivenKey(const std::string &base64ivciphertext, const std::string &base64Key, std::string &plaintextResult );

    // encrypt a file with a given key
    // return 1 for success; 0 for error
    static int encryptFileWithGivenKey(const std::string& inputFile, const std::string& combinedKey, const std::string& outputFile);

    // decrypt a encrypted file back to normal file
    // return 1 for success; 0 for error
    static int decryptFileWithGivenKey(const std::string& inputFile, const std::string& combinedKey, const std::string& outputFile);

    // encrypt file with default key
    // return 1 for success; 0 for error
    int encryptFileWithDefaultKey(const std::string& inputFile, const std::string& outputFile);

    // decrypt file with default key
    // return 1 for success; 0 for error
    int decryptFileWithDefaultKey(const std::string& inputFile, const std::string& outputFile);


	// plotting graph 
	int	 makeGraph( const char *type, const char *title, int width, int height,
					const char *inputFile, const char *outputFile, const char *options );


  protected:
	//JaguarCPPClient *_jcli;
	void         *_jcli;

    std::string  _ipaddress;
    int          _port;
    std::string  _apikey;
    std::string  _dbname;
    std::string  _connOpt;
    unsigned long long _clientFlag;

};


#endif

