#ifndef NODES_H_
#define NODES_H_
#include <iostream>
using namespace std;

//vygenerovani poradoveho cisla
unsigned int getnum();

//zkontrolovani vystupu
bool checkoutput(ostream * output);

//zapis jako VHDL
void printvhdl(ostream* output, bool printvals);

//zapis jako PLA
void printpla(ostream& out);

//zapis jako BLIF
void printblif(ostream& out);

/*=====================================*/
/*abstraktni predek vsech uzlu*/
class Node
{

	public:
	
	//vytvori novou tabulku symbolu ze stromu
	virtual void createSTable();
	
	//vrati true pokud je nalezen typ uzlu dany parametrem
	virtual bool findOp(int pType);
	
	//vrati true pokud je formule spnitelna a odhodnoti promenne hodnotou parametru
	virtual bool equals(unsigned int val);
	
	//zkontroluje semantiku stromu
	virtual bool checkLength(int& g_Length);
	
	//vytvori kopii stromu
	virtual Node * copy()=0;
	
	//test zda strom osahuje jine typy uzlu nez ten dany parametrem (pouze binarni)
	virtual bool containsOp (int num);
	
	//test zda je dany strom v DNF
	virtual bool isdnf(bool bl);
	
	//vrati typ daneho uzlu
	virtual int gettype ()=0;
	
	//zapis stromu do vystupu
	virtual void print(ostream& out)=0;
	
	//vyhodnoceni stromu
	virtual unsigned int eval();
	
	//spocita pocet lireralu ve vyrazu
    virtual unsigned int countLiterals();
    
	//vypise strom pomoci viceurovnoveho popisu
	virtual string printmulti(ostream& out)=0;
	
	/*==========================================================*/
	//vsechny nasledujici metody vrati ukazatel na novy strom a stary zrusi
		
	//zjednoduseni vyrazu
	virtual Node * simplify();
	
	//forma pro realizaci pomoci NANDu
	virtual Node * nandForm();
	
	//forma pro realizaci pomoci NORu
	virtual Node * norForm();
	
	//eliminace dane operace z vyssich hladin stromu - efekt: uprava na NDF nebo NKF
	virtual Node * elimOp(int opType);
	
	//eliminace NOT z vyssich hladin stromu - efekt: NOT je pouze pred listy 
	virtual Node * elimNot();
	
	//"roznasobeni" praveho podstromu danym podstromem, vstupem je ukazatel na dany podstrom
	// a typ pozadovane operace
	virtual Node * applyLR( Node * lop ,unsigned char& pType );
	
	//negovani stromu
	virtual Node * negate();
	
	//uprava daneho stromu do formy kdy obsahuje pouze operatory AND,OR,NOT
	virtual Node * AndOrNot();
	
	//minimalizuje strom vyrazu od listu ke koreni
	virtual Node * minimize();
	
	//nahradi promenne danou hodnotou - kofaktor
	virtual Node * cofactor(int num, bool val);
		
	//destruktor
	virtual ~Node();
};
/*=====================================*/
/*unarni node*/
class UNode : public Node
{
	protected:
    Node * Child;
    unsigned char Type;
   
    public:
    UNode ( Node * Ch, int T);
    
    virtual bool isdnf(bool bl);
    
    virtual bool findOp(int pType);
    
    virtual bool equals(unsigned int val);
    
    virtual bool checkLength(int& g_Length);
    
    virtual void createSTable();
    
    virtual Node * simplify();
    
    virtual Node * nandForm();
    
    virtual Node * norForm();
    
    virtual Node * AndOrNot();
    
    virtual Node * copy();
    
    virtual bool containsOp (int num);
    
    virtual Node * applyLR( Node * lop, unsigned char& pType);
    
    virtual Node * elimOp(int opType);
    
    virtual Node * elimNot();
    
    virtual Node * negate();
    
    virtual void print(ostream& out);
    
    virtual string printmulti(ostream& out);
    
    virtual unsigned int eval ();
    
    virtual Node * minimize();
    
    virtual int gettype();
    
    virtual Node * cofactor(int num, bool val);
    
    virtual unsigned int countLiterals();
    
    virtual ~UNode ( );
};

/*=========================================*/
/*binarni node*/
class BNode : public Node
{
	public:
	//protected:
    Node * Left,* Right; //ukazatele na potomky
    unsigned char Type;  //typ uzlu
   
    public:
    BNode ( Node * L, Node * R, int T );
    
    virtual bool isdnf(bool bl);
    
    virtual bool findOp(int pType);
    
    virtual bool equals(unsigned int val);
    
    virtual bool checkLength(int& g_Length);
    
    virtual void createSTable();
    
    virtual Node * copy();
    
    virtual Node * simplify();
    
    virtual Node * nandForm();
    
    virtual Node * norForm();
    
    virtual Node * AndOrNot();
    
    virtual bool containsOp (int num);
    
    virtual Node * applyLR( Node * lop, unsigned char& pType);
    
    virtual Node * elimOp(int opType);
    
    virtual Node * elimNot();
    
    virtual Node * negate();
    
    virtual void print(ostream& out);
    
    virtual string printmulti(ostream& out);
	
	virtual unsigned int eval ();
	
	virtual int gettype();
	
	virtual Node * minimize();
	
	virtual Node * cofactor(int num, bool val);
	
	virtual unsigned int countLiterals();
	
    virtual ~BNode ( );
};


/*=====================================*/
/*identifikator*/
class IdentNode : public Node 
{
   protected:
   string Name;
   
   public:
   IdentNode ( string& Id );
   
   virtual bool equals(unsigned int val);
   
   virtual Node * copy();
   
   virtual Node * negate();
   
   virtual void print (ostream& out);
   
   virtual string printmulti(ostream& out);
   
   virtual unsigned int eval ();
    
   virtual int gettype();
   
   virtual void createSTable();
   
   virtual unsigned int countLiterals();
   
   virtual Node * cofactor(int num, bool val);
};

/*==========================================*/
/*vektor*/
class VectNode : public Node 
{
   protected:
   unsigned int Value;
   int Length;
   
   public:
   VectNode ( unsigned int V , int L );
   
   virtual bool equals(unsigned int val);
   
   virtual bool checkLength(int& g_Length);
   
   int length();
   
   virtual Node * copy();
   
   virtual Node * negate();
    
   virtual void print(ostream& out);
   
   virtual string printmulti(ostream& out);
   
   virtual unsigned int eval ();
    
   virtual int gettype();
};


Node * minimalization(Node * ptr);

#endif /*NODES_H_*/
