/*
 * Copyright JaguarLite
 *
 * This file is part of JaguarLite.
 *
 * JaguarLite 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. 
 *
 */
#ifndef _jagdb_lite_h_
#define _jagdb_lite_h_

#include <string>
#include <atomic>


class JaguarLite 
{
  public:

	JaguarLite( const char *dbname, const char *tenant = "main" );
	~JaguarLite();



    // return 1 for success:  0: for error
    // For data modification only. Not for query/selects
    int         execute( const std::string &cmd );
    int         execute( const char *cmd );

    // return 1 for success:  0: for error
    int         startExecute( const char *cmd );
    int         endExecute();

    // return 1 for success:  0: for error
    int         startQuery( const char *cmd );
    int         startQuery( const std::string &cmd );
    int         endQuery();
    bool        isDisconnected() { return false; }
    void        reconnect() {}
    std::string getSerialNumber();

    std::string json();
    const char *jsonStr();
    std::string getMessage();
    unsigned long getMessageLen();
    int         printRow();
    int         printAll();

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


    std::string getValue(const char *name);
    std::string getTenant();
    std::string getApiKey() { return ""; }
    std::string makeApiKey() { return ""; }
    double      getDoubleValue(const char *name, bool &found);
    long        getLongValue(const char *name, bool &found);

    bool        hasError();
    std::string error();

    int         read(); 
    int         fetch(); 
    int         readAll();

    std::string getLastZuid();
    void        shutDown();

    //////////////////////////// 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.
    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
    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
    void   encryptWithGivenKey(const std::string &plaintext, const std::string &base64Key, std::string &base64EncodedResult );

    // decrypt base64Encoded text with a key into plaintextResult
    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
    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
    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);
    void  close();
    std::string getException() { return _exception; }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////


    void        *cli;
    std::atomic<bool>  ready;
    std::atomic<bool>  down;

  private:
    int          _sock;
    char         _tenant[64];
    char         _dbname[64];
    bool         _isQuery;
    bool         _hasQueryError;
    pthread_t    _threadjob;
    void         *_sptr;
    std::string  _exception;

    bool         checkMakeLock(const char *dbname, const char *tenant, std::string &reason );

};

#endif
