#ifndef _CEGODBHANDLER_H_INCLUDED_
#define _CEGODBHANDLER_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoDbHandler.h
// ---------------
// Cego db handler class definition
//     
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2019 Bjoern Lemke
//
// INTERFACE MODULE
//
// Class: CegoDbHandler
// 
// Description: Database handler class to the access the database backend via network 
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

// LFC INCLUDES
#include <lfcbase/Logger.h>
#include <lfcbase/NetHandler.h>
#include <lfcxml/XMLSuite.h>

// CEGO INCLUDES
#include "CegoSerial.h"
#include "CegoObject.h"
#include "CegoTableObject.h"
#include "CegoProcVar.h"
#include "CegoBlob.h"
#include "CegoClob.h"
#include "CegoModule.h"

class CegoDbHandler {
    
public:

    enum ProtocolType { XML, SERIAL, FASTSERIAL };

    enum RequestType { QUERY,
		       QUERYABORT,
		       DBPRODINFO,
		       INSERT, 
		       DELETETABLE,
		       UPDATE,
		       CREATETABLE, 
		       CREATEVIEW,
		       CREATEPROCEDURE, 
		       ALTERTABLE, 
		       DROPOBJECT, 
		       CREATEINDEX,
		       CREATECHECK,
		       OBJECTINFO, 
		       GETTABLE, 
		       GETOBJLIST,
		       GETOBJLISTBYTABLE,
		       OBJRENAME,
		       REORGOBJ,
		       SYNC,
		       GETPAGECOUNT,
		       PUTBLOB,
		       GETBLOB,
		       DELBLOB,
		       PUTCLOB,
		       GETCLOB,
		       DELCLOB,
		       STARTTRANSACTION,
		       COMMITTRANSACTION,
		       ROLLBACKTRANSACTION,
		       GETTID,
		       SESSION_CLOSE,
		       REQTIMEOUT,
		       UNKNOWN };

    enum ResultType { DB_OK, DB_ERROR, DB_DATA, DB_INFO, DB_FIN };


    CegoDbHandler(NetHandler *pN, ProtocolType pt, CegoModule *pModule);
    ~CegoDbHandler();

    ////////////////////////////////////
    // client and client node methods //
    ////////////////////////////////////

    ResultType requestSession(const Chain& tableSet, const Chain& user, const Chain& password, bool doEncrypt = true);
    ResultType closeSession();
    ResultType reqQueryOp(const Chain& cmd);
    ResultType reqQueryAbort(unsigned long long idx);

    CegoObject::ObjectType getObjType();
    Element* getObjElement();

    const Chain& getMsg();
    unsigned long long getTid() const;

    const Chain& getDbName() const;
    const Chain& getDbVersion() const;
    const Chain& getDateFormat() const;
    char getQuoteEscapeFlag() const;    
    
    unsigned long long getAffected();
    const ListT<CegoField>& getSchema();
    const Chain& getFormat();

    void getProcResult(ListT<CegoProcVar>& outParamList, CegoFieldValue& retValue);
    ResultType receiveTableData(const ListT<CegoField>& schema);
    ResultType receiveTableData(const ListT<CegoField>& schema, ListT<CegoFieldValue>& fvl);
    void abortQuery();
    void resetQuery();
    bool wasReset();

    /////////////////////////
    // server node methods //
    /////////////////////////

    bool acceptSession();
    RequestType acceptRequest();
    
    Chain getQueryArg();

    void collectSchema(const ListT<CegoField>& schema, const Chain& format = Chain(""));
    void collectData(const ListT<CegoField>& schema);
    void collectData(const ListT<CegoField>& schema, const ListT<CegoFieldValue>& fvl);

    int numCollected() const;
    
    void sendCollectedData();
    void sendFinishData();
    void sendErrorData(const Chain& msg);
    void sendProdInfo();
    void sendObjInfo(CegoDecodableObject& oe);

    void sendSessionConfirm(const Chain& msg, 
			    unsigned long long tid, 
			    const Chain& dbName, 
			    const Chain& dbVersion,
			    const Chain& dateTimeFormat,
			    char quoteEscapeFlag);
	
    void sendResponse(const Chain& msg, unsigned long long affected = 0 );
    void sendError(const Chain& msg );

    void sendBlobInfo(PageIdType pageId);
    void sendBlobSize(unsigned long long blobSize);

    ResultType putBlob(CegoBlob& blob);
    ResultType getBlob(CegoBlob& blob);
    ResultType delBlob(CegoBlob& blob);

    void getPutBlobArg(Chain& tableSet, unsigned long long& blobSize);
    void getGetBlobArg(Chain& tableSet, PageIdType& pageId);

    void sendClobInfo(PageIdType pageId);
    void sendClobSize(unsigned long long blobSize);

    ResultType putClob(CegoClob& clob);
    ResultType getClob(CegoClob& clob);
    ResultType delClob(CegoClob& clob);
    
    void getPutClobArg(Chain& tableset, unsigned long long& clobSize);
    void getGetClobArg(Chain& tableset, PageIdType& pageId);
    
    void sendProcResult(const Chain& msg, const ListT<CegoProcVar>& outParamList, CegoFieldValue *pRetVal);

    const Chain& getTableSet();
    const Chain& getUser();
    const Chain& getPassword();

    NetHandler* getNetHandler();

protected:

    ProtocolType _protType;

    // xml request
    ResultType sendXMLReq(const Chain& reqType, Element* pRoot);
    
    // native serial request
    ResultType sendSerialReq();

    ResultType getMoreTableData();

    NetHandler *_pN;
    CegoModule *_pModule;

    Chain _tableSet;
    Chain _user;
    Chain _password;

    // for xml protocol
    XMLSuite _xml;
    Element **_pRow;
    ListT<Element*> _rowList;

    // for native protocol
    CegoSerial* _pSer;
    Chain _serQueryCmd;
    unsigned long long  _serTid;
    unsigned long long  _serAffected;
    Chain _serMsg;
    Chain _serFormat;

    Chain _serTableSet;
    unsigned long long _serBlobSize;
    unsigned long long _serClobSize;

    PageIdType _serPageId;

    bool _serSync;
    Chain _serDbName;
    Chain _serDbVersion;
    Chain _serDateFormat;
    char _serQuoteEscapeFlag;
    
    ListT<CegoField> _serSchema;

    ListT<CegoProcVar> _outParamList;
    CegoFieldValue _retValue;    

    bool _wasReset;

    unsigned long _modId;
};

#endif
