
//OpenSCADA file: tarchval.h
/***************************************************************************
 *   Copyright (C) 2006-2026 by Roman Savochenko, <roman@oscada.org>       *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; version 2 of the License.               *
 *                                                                         *
 *   This program 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.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef TArchVal_H
#define TArchVal_H

#include <string>
#include <vector>
#include <map>

#include "resalloc.h"
#include "tvariant.h"
#include "tsys.h"

using std::string;
using std::vector;
using std::map;

namespace OSCADA
{

//*************************************************
//* Value archiver                                *
//*************************************************

//*************************************************
//* TValBuf                                       *
//*   Value buffer object. Contain a massif of    *
//* values types: bool, integer (16, 32, 64),     *
//*               real (float, double) or string. *
//*************************************************
class TValBuf
{
    public:
	//Public methods
	TValBuf( );
	TValBuf( TFld::Type vtp, int isz, int64_t ipr, bool ihgrd = false, bool ihres = false );
	TValBuf( const TValBuf &src );
	virtual ~TValBuf( );

	TValBuf &operator=( const TValBuf &src );

	void clear( );

	TFld::Type valType( bool full = false )	{ return full ? mValTp : (TFld::Type)(mValTp&TFld::GenMask); }
	bool hardGrid( )	{ return mHrdGrd; }
	bool highResTm( )	{ return mHgResTm; }
	bool fillLast( )	{ return mFillLast; }
	int size( )		{ return mSize; }
	int realSize( );
	unsigned int evalCnt( )	{ return mEvalCnt; }

	int64_t begin( )	{ return mBeg; }
	int64_t end( )		{ return mEnd; }
	int64_t period( )	{ return mPer; }

	bool vOK( int64_t ibeg, int64_t iend );

	void setValType( TFld::Type vl );
	void setHardGrid( bool vl );
	void setHighResTm( bool vl );
	void setFillLast( bool vl )	{ mFillLast = vl; }
	void setSize( int vl );
	void setPeriod( int64_t vl );

	// Get value
	virtual void getVals( TValBuf &buf, int64_t beg = 0, int64_t end = 0 );
	TVariant get( int64_t *tm = NULL, bool up_ord = false );
	virtual string getS( int64_t *tm = NULL, bool up_ord = false );
	virtual double getR( int64_t *tm = NULL, bool up_ord = false );
	virtual int64_t getI( int64_t *tm = NULL, bool up_ord = false );
	virtual char   getB( int64_t *tm = NULL, bool up_ord = false );

	// Set value
	virtual void setVals( TValBuf &buf, int64_t beg = 0, int64_t end = 0 );
	void set( const TVariant &value, int64_t tm = 0 );
	virtual void setS( const string &value, int64_t tm = 0 );
	virtual void setR( double value, int64_t tm = 0 );
	virtual void setI( int64_t value, int64_t tm = 0 );
	virtual void setB( char value, int64_t tm = 0 );

	void makeBuf( TFld::Type v_tp, int isz, int64_t ipr, bool hd_grd, bool hg_res );	//Create new or change buffer mode (all data into buffer will lost)

    private:
	//Private data and attributes
	template <class TpVal> class TBuf
	{
	    friend class TValBuf;
	    public:
		//Public methods
		TBuf( TpVal eval, int &isz, int64_t &ipr, bool &ihgrd, bool &ihres, bool &iFillLast,
		    int64_t &iend, int64_t &ibeg, unsigned int &iEvalCnt );
		~TBuf( );

		void clear( );

		int realSize( );

		TpVal get( int64_t *tm = NULL, bool up_ord = false );
		void  set( TpVal value, int64_t tm = 0 );

		// Create new or change buffer mode (all data into buffer will lost)
		void makeBuf( int isz, int64_t ipr, bool hd_grd, bool hg_res );

	    private:
		//Private attributes
		bool	&hgResTm,
			&hrdGrd,
			&fillLast;
		int64_t	&end, &beg,
			&per;
		int	&size,
			cur;		//Curent position.
		TpVal	eval;		//Error element value
		unsigned int &mEvalCnt;

		struct SLw  { time_t tm; TpVal val; };
		struct SHg  { int64_t tm; TpVal val; };
		union {
		    vector<TpVal>	*grid;
		    vector<SLw>		*tmLow;
		    vector<SHg>		*tmHigh;
		} buf;
	};

	ResRW		bRes;		//Access resource
	TFld::Type	mValTp;		//Store values type
	union {
	    TBuf<char>		*bl;
	    TBuf<int16_t>	*i16;
	    TBuf<int32_t>	*i32;
	    TBuf<int64_t>	*i64;
	    TBuf<float>		*rFlt;
	    TBuf<double>	*rDbl;
	    TBuf<string>	*str;
	} buf;

	bool	mHgResTm,		//High resolution time use (microseconds)
		mHrdGrd,		//Set hard griding. It mode no support the zero periodic
		mFillLast;		//Fill pass points by previous value at insert value more to one
	int64_t	mEnd, mBeg,		//Time of buffer begin and end (64 bit usec)
		mPer;			//Periodic grid value (usec). If value = 0 then it no periodic buffer, error for time griding mode!
	int	mSize;			//Buffer size limit.
	unsigned int mEvalCnt;
};

//*************************************************
//* TVArchive                                     *
//*************************************************
class TVal;
class TArchiveS;
class TVArchEl;

class TVArchive : public TCntrNode, public TValBuf, public TConfig
{
    public:
	//Public data
	enum SrcMode {
	    SRC_SaveCur = -1,
	    SRC_Passive = 0,
	    SRC_DAQAttr,
	    SRC_DAQAttrAct	//Mostly for cases of multiple archiving one attribute from a task of values active archiving
	};
	enum CombMode { CMB_MovAver = 0, CMB_LastVal, CMB_MinVal, CMB_MaxVal, CMB_FromArchiver };
	enum ServReqDtMode { DM_Simple = 0, DM_Pack, DM_Bin };

	//Public methods
	TVArchive( const string &id, const string &db, TElem *cf_el );
	~TVArchive( );

	string objName( );

	TCntrNode &operator=( const TCntrNode &node );

	// Base functions
	string	id( )			{ return mId; }
	string	name( );
	string	dscr( )			{ return cfg("DESCR").getS(); }
	SrcMode	srcMode( )		{ return (TVArchive::SrcMode)mSrcMode.getI(); }
	string	srcData( )		{ return mSource; }
	TVArchive::CombMode combMode( )	{ return (TVArchive::CombMode)mCombMode.getI(); }
	AutoHD<TVal> srcPAttr( bool force = false, const string &ipath = "" );
	bool	toStart( )  		{ return mStart; }
	bool	startStat( ) const	{ return runSt; }

	string	DB( bool qTop = false ) const		{ return storage(mDB, qTop); }
	string	tbl( );
	string	fullDB( bool qTop = false )		{ return DB(qTop)+'.'+tbl(); }

	int64_t	end( const string &arch = ARCH_BUF );
	int64_t	begin( const string &arch = ARCH_BUF );
	int64_t	period( const string &arch = ARCH_BUF );
	TFld::Type valType( bool full = false )	{ return TValBuf::valType(full); }
	bool	hardGrid( )	{ return TValBuf::hardGrid(); }
	bool	highResTm( )	{ return TValBuf::highResTm(); }
	bool	fillLast( )	{ return TValBuf::fillLast(); }
	int	size( )		{ return TValBuf::size(); }

	void setName( const string &inm )	{ cfg("NAME").setS(inm); }
	void setDscr( const string &idscr )	{ cfg("DESCR").setS(idscr); }
	void setSrcMode( SrcMode vl = SRC_SaveCur, const string &isrc = "<*>", bool noex = false );
	void setCombMode( TVArchive::CombMode vl )		{ mCombMode = (int)vl; }
	void setToStart( bool vl )		{ mStart = vl; modif(); }

	void setDB( const string &vl, bool qTop = false )	{ setStorage(mDB, vl, qTop); if(!qTop) modifG(); }

	void setValType( TFld::Type vl )	{ mVType = vl; }
	void setHardGrid( bool vl )		{ mBHGrd = vl; setUpBuf(); modif(); }
	void setHighResTm( bool vl )		{ mBHRes = vl; setUpBuf(); modif(); }
	void setFillLast( bool vl )		{ mFillLast = vl; TValBuf::setFillLast(vl); modif(); }
	void setSize( int vl )			{ mBSize = vl; }
	void setPeriod( int64_t vl );

	// Service
	void start( );
	void stop( bool full_del = false );

	// Get value
	TVariant getVal( int64_t *tm = NULL, bool up_ord = false, const string &arch = "", bool onlyLocal = false );
	void getVals( TValBuf &buf, int64_t beg = 0, int64_t end = 0,
		const string &arch = "", int limit = 100000, bool onlyLocal = false );
	void setVals( TValBuf &buf, int64_t beg, int64_t end, const string &arch );

	// Active get data from atribute
	void getActiveData( const int64_t &tm = 0 );

	// Phisical archiver's functions
	void archivatorList( vector<string> &ls );
	bool archivatorPresent( const string &arch );
	void archivatorAttach( const string &arch );
	void archivatorDetach( const string &arch, bool full = false, bool toModify = true );
	void archivatorSort( );

	string makeTrendImg( int64_t beg, int64_t end, const string &arch,
	    int hsz = 650, int vsz = 230, double valmax = 0, double valmin = 0, string *tp = NULL );

	TArchiveS &owner( ) const;

	void cntrCmdProc( XMLNode *opt );       //Control interface command process

    protected:
	//Protected methods
	void preDisable( int flag );
	void postDisable( int flag );
	bool cfgChange( TCfg &co, const TVariant &pc );

	void load_( TConfig *cfg );
	void save_( );

	TVariant objFuncCall( const string &id, vector<TVariant> &prms, const string &user_lang );

    private:
	//Private methods
	void setUpBuf( );
	const char *nodeName( ) const	{ return mId.getSd(); }

	//Private attributes
	ResRW	aRes;
	bool	runSt;
	string	mDB;

	TCfg	&mId,		//ID
		&mVType,	//Value type (int, real, bool, string)
		&mSrcMode,	//Source mode
		&mSource,	//Source
		&mCombMode,	//Data combining mode (Moving average, Single, Minimum, Maximum, From Archiver)
		&mBPer,		//Buffer period
		&mBSize;	//Buffer size
	char	&mStart,	//Starting flag
		&mBHGrd,	//Buffer use hard time griding
		&mBHRes,	//Buffer use high time resolution
		&mFillLast;	//Fill pass points by previous value at insert value more to one
	// Mode params
	AutoHD<TVal>	pattrSrc;
	// Phisical archive's elements
	vector<TVArchEl*> archEl;	//Links
};

//*************************************************
//* TVArchivator                                  *
//*************************************************
class TTypeArchivator;

class TVArchivator : public TCntrNode, public TConfig
{
    friend void TVArchive::archivatorAttach( const string &arch );
    friend void TVArchive::archivatorDetach( const string &arch, bool full, bool toModify );

    public:
	//Public methods
	TVArchivator( const string &id, const string &db, TElem *cf_el );
	~TVArchivator( );

	TCntrNode &operator=( const TCntrNode &node );

	string	id( )		{ return mId; }
	string	workId( );
	string	name( );
	string	dscr( )		{ return cfg("DESCR").getS(); }
	bool toStart( )		{ return mStart; }
	string	addr( ) const	{ return cfg("ADDR").getS(); }
	double	valPeriod( )	{ return mVPer; }
	int	archPeriod( )	{ return mAPer; }
	int	selPrior( )	{ return mSelPrior; }
	TVArchive::CombMode combMode( )	{ return (TVArchive::CombMode)mCombMode.getI(); }

	bool startStat( ) const	{ return runSt; }

	string DB( bool qTop = false ) const	{ return storage(mDB, qTop); }
	string tbl( );
	string fullDB( bool qTop = false )	{ return DB(qTop)+'.'+tbl(); }

	void setName( const string &inm )	{ cfg("NAME").setS(inm); }
	void setDscr( const string &idscr )	{ cfg("DESCR").setS(idscr); }
	void setToStart( bool vl )		{ mStart = vl; modif(); }
	void setAddr( const string &vl )	{ cfg("ADDR").setS(vl); }
	void setValPeriod( double per )		{ mVPer = per; }
	void setArchPeriod( int per )		{ mAPer = per; }
	void setSelPrior( int vl )		{ mSelPrior = std::max(0,std::min(1000,vl)); modif(); }
	void setCombMode( TVArchive::CombMode vl ) { mCombMode = (int)vl; }

	void setDB( const string &vl, bool qTop = false )	{ setStorage(mDB, vl, qTop); if(!qTop) modif(); }

	virtual void start( );
	virtual void stop( bool full_del = false );

	TVariant objFuncCall( const string &id, vector<TVariant> &prms, const string &user_lang );

	// Place archive functions
	void archiveList( vector<string> &ls );
	bool archivePresent( const string &iid );

	TTypeArchivator &owner( ) const;

    protected:
	//Protected methods
	// Protected place archive functions
	TVArchEl *archivePlace( TVArchive &item );
	void archiveRemove( const string &id, bool full = false );

	virtual TVArchEl *getArchEl( TVArchive &arch );

	virtual void pushAccumVals( )	{ };

	void cntrCmdProc( XMLNode *opt );	//Control interface command process
	void postEnable( int flag );
	void preDisable( int flag );
	void postDisable( int flag );		//Delete all DB if flag 1
	bool cfgChange( TCfg &co, const TVariant &pc );

	void load_( TConfig *cfg );
	void save_( );

	//Protected attributes
	ResRW	archRes;
	bool	runSt, endrunReq;
	// Phisical elements storing
	map<string,TVArchEl*> archEl;

    private:
	//Private methods
	const char *nodeName( ) const	{ return mId.getSd(); }
	static void *Task( void *param );	//Process task

	//Private attributes
	TCfg	&mId,		//Var arch id
		&mVPer,		//Value period (sec)
		&mAPer,		//Archivation period
		&mCombMode;	//Data combining mode (Moving average, Single, Minimum, Maximum)
	char	&mStart;	//Var arch starting flag
	int64_t	&mSelPrior;	//Selection priority
	string	mDB;
};

//*************************************************
//* TVArchEl                                      *
//*************************************************
class TVArchEl
{
    friend class TVArchivator;

    public:
	//Public methods
	TVArchEl( TVArchive &iarchive, TVArchivator &iarchivator );
	virtual ~TVArchEl( );
	virtual void fullErase( )	{ }

	virtual int64_t end( )		{ return 0; }		//Archive end
	virtual int64_t begin( )	{ return 0; }		//Archive begin
	int64_t lastGet( )		{ return mLastGet; }	//Last getted value time

	TVariant getVal( int64_t *tm, bool up_ord, bool onlyLocal = false );
	void getVals( TValBuf &buf, int64_t beg = 0, int64_t end = 0, bool onlyLocal = false );
	void setVals( TValBuf &buf, int64_t beg = 0, int64_t end = 0, bool toAccum = false );

	TVArchive &archive( );
	TVArchivator &archivator( );

	//Public attributes
	int64_t	mLastGet;

    protected:
	//Protected methods
	virtual TVariant getValProc( int64_t *tm, bool up_ord );
	virtual void getValsProc( TValBuf &buf, int64_t beg, int64_t end )	{ }
	virtual int64_t setValsProc( TValBuf &buf, int64_t beg, int64_t end, bool toAccum )	{ return 0; }

	// Previous averaging value
	int64_t	prevTm;
	double	prevVal;

    private:
	//Private attributes
	TVArchive	&mArchive;
	TVArchivator	&mArchivator;
};

}

#endif // TArchVal_H
