/***********************************************************************************************************************
//	New qmgr do compression to blob so we dont have to.
************************************************************************************************************************/

#if !defined(__DATACACHE__)
#define __DATACACHE__

#if defined(__DB_OFFLINE__)
	#include "structifx.hpp"
	#include "normbase.hpp"
#else
	#include <StructIfx/structifx.hpp>
	#include <shlu2/BasicUtils/normbase.hpp>
#endif
#include <vector>
#include <map>

#include <iostream>

constexpr const char * SIDFIELDDELIMIT = "-";
// -- universal data id structure
struct TDataKey
{
    std::string signature;
	std::string service_name;
    std::string data_name;
    
    TDataKey(void): signature(k_strEmptyString), service_name(k_strEmptyString), data_name(k_strEmptyString) {};
    
    
	TDataKey(const std::string &sig, const std::string &svc, const std::string &dname=k_strEmptyString):
		signature(sig), service_name(svc), data_name(dname) {};
    
	virtual ~TDataKey(void){};
	virtual int ParseHandle(const std::string &handle) = 0;	//for future expansion, override this. return number of fields handled
	
	void MakeHandle(std::string &handle) const;
	virtual std::string MakeHandle(void) const = 0;
	
	operator std::string (void) const;
};

class CDataCache
{
public:
    
	static constexpr const size_t BUFFSIZE = 20971520;	//exactly 20MB
	static constexpr const size_t BUFMARGIN = 5242880;	//exactly 5MB
	
	enum ECacheError
	{
		eDataOk = 0,
		eInvalidKey,
		eNoData,
        eDataProcessing,
		eModeError,
		eProcessError,	//compress/decompress
        eFailToObtainStorage,
		eFailToStoreData,	// -- fail to transfer blobs to server
        eAbusive,
		eUnknown,
		eCacheErrorStop
	};


	enum ECacheMode
	{
		eRead = 0,
		eWrite = 2
	};

	virtual ~CDataCache(void);
	
	//void Reset(const std::string &handle, int mode = eRead, unsigned int usrip = 0);
	//void Reset(unsigned int usrip = 0, const std::string & svcname = k_strEmptyString);
	
	// -- save current block and reset block for new data
	int Flush(void);
	int Load(void);
	
	void PushData(const void* pData, size_t ulSize);
	void ReadData(void* pData, size_t ulSize);
	
	void PushString(const std::string &rStr);
	void ReadString(std::string& rStr);
	
	void PushCString(const char *pStr);
	char* ReadCString(void);
	
    
    virtual std::string GetHandle(void) const = 0;
    virtual void Reset(int mode, const std::string &handle) = 0;
    virtual void Reset(const std::string & svcname) = 0;   //reset internal 
    void ResetData(int mode = -1);
    
    unsigned int GetUserIp(void) const {return m_usr_ip4;}
    void SetUserIp(unsigned int ip) {m_usr_ip4 = ip;}
    

	/*********** for convenience and abstraction *****************/
	static const char * MsgString(int errCode);
protected:
    //CDataCache(void) = default;
	CDataCache(int mode, unsigned int usr_ip4 = 0);	//default write mode
    
    CDataCache(const CDataCache& src) = delete;
	const CDataCache & operator = (const CDataCache& src) = delete;
    
    unsigned int m_usr_ip4;
	int m_iMode;
	char *m_pBuf;
	size_t m_ulBytesAvailable;  //available (to read) bytes in buf
	size_t m_ulCurrPos;	//current position -- data pointer
	int m_iBlockIdx;	//count blocks
	bool m_bDirty;	//dirty flag-- has data that is not on server (been written)
	
    //virtual const TDataKey & x_GetDataKey(void) const = 0;
    //virtual TDataKey & x_SetDataKey(void) = 0;
	virtual int x_SaveBlock(int bidx, const char *src, size_t n) const = 0;
	virtual int x_RetrieveBlock(int bidx, char *dst, size_t &n) const = 0;
	
	static const char * m_dimStatusLits[eCacheErrorStop];	
};

class Cacheable
{
public:
    virtual ~Cacheable(void) {};
    virtual void SaveToCache(CDataCache &dc) const = 0;
    virtual void RestoreFromCache(CDataCache &dc) = 0;
};

#include "impl/datacache_impl.hpp"

#endif
