#ifndef __FORMULE_HPP__
#define __FORMULE_HPP__

#include <iostream>
#include "promenljive.hpp"

class Formula
{
public:
	virtual void ispisi(ostream& ostr) = 0;
	virtual int vrednost() = 0;
	virtual ~Formula() 
	{}
};

class Slovo : public Formula
{
public:
	Slovo(char p)
		: _p(p)
	{}

	void ispisi(ostream& ostr)
	{
		ostr<<_p;
	}
	
	int vrednost()
	{
		return vrednost_promenljive(_p);
	}

private:
	char _p;
};

class Konstanta : public Formula
{
public:
	Konstanta(int vrednost)
	:	_vrednost(vrednost)
	{}

	void ispisi(ostream& ostr)
	{
		ostr<<(_vrednost?'T':'F');
	}

	int vrednost()
	{	return _vrednost;	}

private:
	int _vrednost;	
};

class Veznik : public Formula
{
public:
	Veznik(const string& symbol, Formula* op1, Formula* op2)
		: _symbol(symbol), _op1(op1), _op2(op2)
	{}

	~Veznik()
	{	delete _op1;
		delete _op2;
	}

	void ispisi(ostream& ostr)
	{
		ostr<<'(';
		_op1->ispisi(ostr);
		ostr<<')';
		ostr<<_symbol;
		ostr<<'(';
		_op2->ispisi(ostr);
		ostr<<')';
		
	}
protected:
	Formula *_op1, *_op2;
	string _symbol; 
	
};

class Konjunkcija : public Veznik
{
public:
	Konjunkcija(Formula* op1, Formula* op2)
		: Veznik("/\\", op1, op2)
	{}

	int vrednost()
	{
		return _op1->vrednost() && _op2->vrednost();
	}
};

class Disjunkcija : public Veznik
{
public:
	Disjunkcija(Formula* op1, Formula* op2)
		: Veznik("\\/", op1, op2)
	{}

	int vrednost()
	{
		return _op1->vrednost() || _op2->vrednost();
	}
};

class Implikacija : public Veznik
{
public:
	Implikacija(Formula* op1, Formula* op2)
		: Veznik("=>", op1, op2)
	{}

	int vrednost()
	{
		return !_op1->vrednost() || _op2->vrednost();
	}
};

class Negacija : public Formula
{
public:
	Negacija(Formula* op)
		: _op(op)
	{}

	~Negacija()
	{
		delete _op;
	}

	void ispisi(ostream& ostr)
	{
		cout<<"~(";
		_op->ispisi(ostr);
		cout<<")";
	}

	int vrednost()
	{
		return !_op->vrednost();
	}

private:
	Formula* _op;
};

#endif
