/////////////////////////////////////////////////////////////////////////////
// Name:        
// Purpose:     wxBugTracker
// Author:      Aleksandras Gluchovas (mailto:alex@soften.ktu.lt)
// Modified by:
// Created:     20/10/1999
// RCS-ID:      $Id: eq_solver.h,v 1.3 2001/02/08 11:05:08 georgetasker Exp $
// Copyright:   (c) Aleksandras Gluchovas
// Licence:   	GPL (version 2.0 or later)
/////////////////////////////////////////////////////////////////////////////


#ifndef __EQ_SOLVER__
#define __EQ_SOLVER__

#include "wx/string.h"
#include "wx/hash.h"
#include "wx/dynarray.h"
#include "wx/tokenzr.h"

#include "strlist.h"
#include "myutils.h"

extern wxString IntToStr(int);

class EqSolver;
class EqSolverNode;

enum EQ_SOLVER_VAR_TYPES
{
	EQS_INT,
	EQS_DOUBLE,
	EQS_STRING
};

class EqSolverVar : public wxObject
{
public:
	EqSolverVar();
	EqSolverVar( double d );
	EqSolverVar( const wxString& strValue );
	EqSolverVar( const wxString& name, double d );
	EqSolverVar( const wxString& name, const wxString& strValue );

	virtual void SetName( const wxString& name );
	virtual const wxString& GetName();
	virtual void SetType( int type );
	virtual int   GetType();
	
	void SetDouble( const double d );
	void SetString( const wxString& s );
	double GetDouble();
	bool GetBool();
	wxString& GetString();

protected:
	// FOR NOW:: all in one...
	wxString mName;
	wxString mStrValue;
	double   mDoubleValue;
	int		 mType;
};

typedef bool (*EqSolverEvalFunct)( EqSolverVar& arg1, EqSolverVar& arg2, EqSolverVar& result );

class EqSolverNode : public wxObject
{
public:
	virtual bool Evaluate( EqSolverVar& result, EqSolver& solver ) = 0;

	virtual bool EvaluateBool( EqSolver& solver );
	virtual double EvaluateDouble( EqSolver& solver );
	virtual int EvaluateInt( EqSolver& solver );
	virtual wxString EvaluateString( EqSolver& solver );

	DECLARE_CLASS( EqSolverNode )
};

class EqBinaryOpNode : public EqSolverNode
{
public:
	EqBinaryOpNode( EqSolverEvalFunct evalFunct );
	EqBinaryOpNode( EqSolverNode* pNode1, EqSolverNode* pNode2, EqSolverEvalFunct evalFunct );

	virtual bool Evaluate( EqSolverVar& result, EqSolver& solver );
	
	virtual void SetLeftNode( EqSolverNode* pLeft );
	virtual void SetRightNode( EqSolverNode* pRight );

	DECLARE_CLASS( EqBinaryOpNode )
protected:
	EqSolverNode* mpNode1;
	EqSolverNode* mpNode2;

    EqSolverEvalFunct mEvalFunct;
};

class EqUnaryNotNode : public EqSolverNode
{
public:
	EqUnaryNotNode( EqSolverNode* pNode1 );

	virtual bool Evaluate( EqSolverVar& result, EqSolver& solver );

	DECLARE_CLASS( EqUnaryNotNode )
protected:
	EqSolverNode* mpNode1;
};

class EqVarNode : public EqSolverNode
{
public:
	EqVarNode( const wxString& varName );

	virtual bool Evaluate( EqSolverVar& result, EqSolver& solver );

	DECLARE_CLASS( EqVarNode )
protected:
	wxString mVarName;
};

class EqConstNode : public EqSolverNode
{
public:
	EqConstNode( const EqSolverVar& constValue );

	virtual bool Evaluate( EqSolverVar& result, EqSolver& solver );

	DECLARE_CLASS( EqConstNode )
protected:
	EqSolverVar mConstValue;
};

WX_DEFINE_ARRAY( EqSolverVar*, EqSolverVarListT );

class EqSolver : public wxObject
{
public:
	EqSolver();
	~EqSolver();

	// auto-detects type from string
	virtual void SetVar( const wxString& name, const wxString& value );
	virtual void SetStringVar( const wxString& name, const wxString& value );
	virtual void SetIntVar( const wxString& name, int value );
	virtual void SetDoubleVar( const wxString& name, double d );

	virtual void RemoveVar( const wxString& name );

	virtual EqSolverVar* FindVar( const wxString& name );
	virtual wxString GetStringValue( const wxString& name );

	virtual EqSolverVar* Evaluate( const wxString& exprText );
	virtual bool EvaluateToBool( const wxString& exprText );
	virtual void ResetAllVars();

protected:

	bool HasTureValue( const wxString& varName );
	void AddVar( EqSolverVar* pVar );

protected:
	EqSolverVarListT mVars;
	wxHashTable		 mVarsHash;
};

EqSolverNode* ParseExpr( const wxString& exprText );
EqSolverNode* ParseSingleNode( wxStringTokenizer& tok, const wxString& tk );
EqSolverNode* DoParseExprRecursive( wxStringTokenizer& tok, const wxString& tk );


class ScriptPreprocessor : public wxObject
{
public:
	ScriptPreprocessor();
	~ScriptPreprocessor();

	// accepts following tokens:
	//
	// #if <expr>
	// #endif
	// #elif <expr>
	// #else
	// #endif
	// ##VAR##

	// returns preprocessed text
	virtual wxString Process( const wxString& sourceText, EqSolver* pSolver );

protected:
	virtual wxString ProcessBlockRecursively( char*& cur, char* end, bool isNestedBlock );
	virtual void OutputBlock( wxString& outText, char*& from, char* till );
	virtual bool EvalExpr( char*& cur, char* till );
	virtual void SkipExpr( char*& cur, char* till );

protected:
	EqSolver* mpSolver;
	char* mpBuf;
	char* mpBufPos;
	bool  mBufLocked;
};


void TestEqSolver();

#endif // __EQ_SOLVER__
