#ifndef _CEGOFUNCTION_H_INCLUDED_
#define _CEGOFUNCTION_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoFunction.h
// --------------
// Cego internal sql function class definition
//     
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2019 Bjoern Lemke
//
// INTERFACE MODULE
//
// Class: CegoFunction
// 
// Description: All internal SQL database functions
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

#include <lfcbase/Chain.h>
#include <lfcbase/ListT.h>

#include "CegoAttrDesc.h"
#include "CegoField.h"
#include "CegoFieldValue.h"
#include "CegoProcBlock.h"

class CegoProcedure;
class CegoDistManager;
class CegoTableManager;
class CegoAggregation;
class CegoExpr;
class CegoDatabaseFormater;

class CegoFunction {
    
public:
    
    enum FunctionType { INT2ASC,
			ASC2INT,
			TRIM, 
			RTRIM,
			LTRIM,
			ROUND,
			DATE2STR, 
			DATE2LONG, 
			LONG2DATE,
			NEWDATE,
			LEFT,
			RIGHT,
			GETPOS,
			SUBSTR,
			REPLACE,
			LENGTH,
			LOWER,
			UPPER,
			TRUNC,
			STR2INT,
			STR2LONG,
			STR2DATE,
			RANDSTR,
			RANDINT,
			MOD,
			DIV,
			LMOD,
			LDIV,
			POWER,
			BITAND,
			BITOR,
			BITXOR,
			BLOBSIZE,
			BLOBREF,
			CLOBSIZE,
			CLOBREF,
			CLOB2STR,
			NEXTCOUNT,
			SETCOUNT,
			USERDEFINED };
    
    CegoFunction(FunctionType funcType);
    CegoFunction(FunctionType funcType, ListT<CegoExpr*>& exprList);

    CegoFunction(char* buf, CegoDistManager *pTabMng, int tabSetId);
    CegoFunction(CegoDistManager* pTabMng, int tabSetId, CegoFunction::FunctionType type);
    CegoFunction(CegoDistManager* pTabMng, int tabSetId, const Chain& funcName, ListT<CegoExpr*>& exprList);
    
    CegoFunction(Element* pFunctionElement, CegoDistManager *pGTM);

    ~CegoFunction();

    void cleanUp();

    void setTabSetId(int tabSetId);
    
    int getTabSetId() const;
    Chain getName() const;
	
    CegoDataType getReturnType() const;
    int getReturnTypeLen(const ListT<CegoField>& fl) const;

    ListT<CegoExpr*>& getExprList();
    void getFieldList(ListT<CegoField>& fl) const;
    void setFieldListArray(ListT<CegoField>** pFLA);
    void setBlock(CegoProcBlock *pBlock);

    const FunctionType getType() const;

    void setExprList(ListT<CegoExpr*>& exprList);

    void clearAttrCache();

    ListT<CegoAttrDesc*> getAttrRefList() const;
    int evalReferences(CegoContentObject *pCO, const ListT<CegoField>& fl);

    void setCounterId(const Chain& counterId);
    void setCounterExpr(CegoExpr* pCounterExpr);

    ListT<CegoAggregation*> getAggregationList();
    
    CegoFieldValue evalFieldValue() const;
    Chain getId() const;
    Chain toChain(const Chain& indent = Chain("")) const;
    Chain dbFormat(CegoDatabaseFormater *pForm) const;
    
    Element* toElement() const;
    void fromElement(Element *pFunctionElement, CegoDistManager *pGTM);

    void encode(char *buf);
    void decode(char *buf, CegoDistManager* pGTM, int tabSetId);
    int getEncodingLength() const;

    CegoFunction* clone(bool isAttrRef = false);

    CegoFunction& operator = ( const CegoFunction& f);

    friend ostream& operator << (ostream& s, const CegoFunction& f);
      
private:

    CegoProcedure* loadProcedure(int tabSetId, const Chain& procName) const;
    
    CegoDistManager* _pTabMng;
    CegoProcBlock* _pBlock;
    Chain _funcName;
    Chain _counterId;
    
    FunctionType _type;
    ListT<CegoExpr*> _exprList;
    int _tabSetId;
};

#endif
