#include <windows.h>
#include "cdatabase.h"
#include "cmemory.h"
#include "csyntactic.h"
#include "cgraph.h"
#include "cinfowin.h"

#define	DATALOG_OK					1
#define DATALOG_WARNING				2
#define DATALOG_ERROR				3

#define DATALOG_ERR_NOTBINDED		1			//premenna nie je viazana
#define DATALOG_ERR_TYPE			2			//premenna pouzita v zlom typovom kontexte
#define DATALOG_ERR_MUSTGROUPBY		4			//premenna nevystupuje v groupby predikate (a musi tam byt)
#define DATALOG_ERR_MUSTREL			8			//premenna musi byt viazana v relacnom podcieli
#define DATALOG_ERR_BADDATE			16			//zly format datumu
#define DATALOG_ERR_USEAGRFUN		32			//premenna nesmie obsahovat agregacne funkcie
#define DATALOG_ERR_INHEAD			64			//premenna sa nesmie vyskytovat v hlavicke (nie je v groupby alebo s agreg. funkciami)

//varTypes[].mark
#define	DATALOG_MARKED_BINDEDASS				1		//viazana v priradeni ( ass:)-ignment )
#define	DATALOG_MARKED_BINDEDREL				2		//viazana v relacnom podcieli
#define	DATALOG_MARKED_GROUPBY					4		//v groupby
#define	DATALOG_MARKED_SUBS						8		//premenna, ktora je viazana na lavej strane substitucie
#define DATALOG_MARKED_ASSIGN_ONLY_AGRFUN		16		//priradenie, na pravej strane ktoreho su len konstanty, premenne v groupby,
														//agrfun a premenne v takomto priradeni
														//agrfunkcia tu vsak nemusi byt; v tomto vsak musi:
														//DATALOG_MARKED_ASSIGN_SOME_AGRFUN&DATALOG_MARKED_ASSIGN_ONLY_AGRFUN
#define DATALOG_MARKED_ASSIGN_SOME_AGRFUN		32		//priradenie, na pravej strane ktoreho je aspon jedna agrfunkcia v tran.uzav.
														//pouzite len v suvislosti s DATALOG_MARKED_ASSIGN_ONLY_AGRFUN

//vystpuju vo vyrazoch (expression)
//pozor na definiciu *_agrFunctionsName[]
#define DATALOG_EXP_VAR				0x01
#define DATALOG_EXP_SUM				0x02
#define DATALOG_EXP_AVG				0x03
#define DATALOG_EXP_COUNT			0x04
#define DATALOG_EXP_MIN				0x05
#define DATALOG_EXP_MAX				0x06
#define DATALOG_EXP_SPECIAL			0x07

//CanBeDate
#define	DATALOG_DATE_YES			1
#define	DATALOG_DATE_OVERFLOW		2
#define	DATALOG_DATE_NO				3


#define DATALOG_NUMOF_NUM_TYPES		9

#ifndef __DATALOGCLASS
#define __DATALOGCLASS

class CDatalog
{
	private:
		CGraph *graph;
		CSyntacticAnalyzer *sa;
		CStringTable *argsAnswer;//mena premennych sa pri semantickej kontrole prepisuju, uchovaj si kvoli vystupu mena pre answer atom
		const SYNTACTIC_TABLE_RULES *table;

		void TopologicalSort(CMemory *vertexList, DWORD root);	//topologicky utriedi prvky v poli podla roota
																//nedostupne (nespojene s rootom nejakou cestou) vrcholy odstrani
		DWORD CheckSemantic();//overi semantiku pravidiel, vrati DATALOG_OK/WARNING/ERROR

		void DeleteAllTables(CStringTable *tableNames);
		CInfoWindow *infoWin;

		CSQLresult *EvaluateWithoutLoop(CMemory *ord_list);//ord_list je topologicky utriedeny zoznam IDB atomov
		CSQLresult *EvaluateWithLoop();

		//v databaze vytvori docasne tabulky pre IDB atomy
		//ak nastane chyba, hodi exception a tabulky zmaze
		CStringTable *CreateAllTables(bool seminaive);

		DWORD CanBeDate(char *str);//overi, ci ide o datum a vrati hlasku DATALOG_DATE

		static char *_agrFunctionsName[];

		static LRESULT CALLBACK StaticWindowProcViewResult(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp);

		void ViewResult(CSQLresult *res);//zobrazi vysledok ako html stranku

		BYTE CheckAgregFunType(DWORD funId, SYNTACTIC_RULE *rule, DWORD *ret);//overi spravnost typu argumentu v agr. funkcii a vrati typ, ktory fun. vracia
		DWORD CDatalog::GetMaxStratumForVar(SYNTACTIC_RULE *rule, DWORD varId, DWORD *strata);//vrati max. stratum zo vsetkych rel.atomov, v ktorych sa viaze premenna varId
		void EvaluateStratum(DWORD *pred, DWORD count);
		void CreateFromPart(SYNTACTIC_RULE *rule, CMemory *output, DWORD predIndex);//vo WHERE klauzule nahradi predIndex-ty predikat P(temp) deltaP(demp)
		CStringTable **CreateSQLQueries();//vytvori a zapise do sqlQueries SQL dotazy
		CStringTable **CDatalog::CreateSQLQueriesEx(DWORD *idbPred, DWORD count, bool seminaive);//vytvori a zapise do sqlQueries SQL dotazy
		DWORD GetAllNotMarkedVars(SYNTACTIC_RULE *rule, DWORD varId, BYTE *marked, CMemory *tmp, DWORD *ret);
		BYTE GetTypeInExpression(char *exp, DWORD &i, SYNTACTIC_RULE *rule);
		DWORD GetPredicateOfBinding(DWORD varId, SYNTACTIC_RULE *rule, DWORD *index);
		DWORD GetAssignmentOfBinding(DWORD varId, SYNTACTIC_RULE *rule);
		BYTE AllSubexpressionMustBeNumbers(DWORD atomId, char *exp, SYNTACTIC_RULE *rule, DWORD *ret);
	public:
		CDatalog(void* input);//input je vstupny text
		bool Evaluate();
		~CDatalog();

		static char *ExpressionToString(SYNTACTIC_RULE* rule,char *exp, bool sql);//skonvertuje vyraz s premennymi tvaru (01 id id id id) na string ich substituovanim z rule->varNames
		//..ak sa vo vyraze objavila agregacna funkcia, nastavi _agrInExp na TRUE
		static bool _agrInExp;
		static char *StringToExpression(SYNTACTIC_RULE *rule, CMemory *var_used, SYNTACTIC_ATOM_FULLNAME_ARIT* arit);//vytvori vyraz nahradenim premennych do tvaru (01 id id id)
		static DWORD ExpressionLength(char *exp);//vrati dlzku vyrazu
};		

#endif