#include "hub.h"
#include <set>

using namespace std;

class TVnitrni;
class TVnejsi;
class THradlo;

class THotove_hradlo {
  public:
	int pocet;  // na kolik vstupu de vystup
	TVnejsi *hradlo;  // ukazatel na hotove hradlo
};

class Collapsing {
#ifdef DEBUG
	int casAnd,casNand,casOr,casNor,casNot,casXor,casXnor,casEsp,casAbs;
	int pocAnd,pocNand,pocOr,pocNor,pocNot,pocXor,pocXnor,pocEsp,pocAbs;
#endif
	int INPUT;
	char *arg[5];  // argumenty prikazove radky
	string *vstupy;
	map<std::string,THotove_hradlo> seznam_hradel;  // seznam uz hotovych hradel, ktere se jeste pouzijou
	TVnejsi* my_and(THradlo* hr);
	TVnejsi* my_or(THradlo* hr);
	TVnejsi* my_nor(THradlo* hr);
	TVnejsi* my_nand(THradlo* hr);
	TVnejsi* my_not(TVnejsi* vn);
	TVnejsi* minim_hradlo(std::string hradlo, hub::StructArch* sa, bool negace = false);
	void absorpce(TVnejsi* nove, int* novy_soucin);
	TVnejsi* minim(TVnejsi* nove);
  public:
	Collapsing(int ac, char *a[]){
		arg[1] = "result.pla";
		arg[2] = "-1";  // pri kolika a vice hradlech se pouzije Espresso
		arg[3] = "false";  // zda se pouzije Espresso na vysledek
		arg[4] = "true";  // zda se pouzije absorpce
		switch (ac) {
			case 6: arg[4] = a[5];
			case 5: arg[2] = a[4];
			case 4: arg[3] = a[3];
			case 3: arg[1] = a[2];
				break;
		}
	}
	void minimalize(hub::Hub theHub);
};

class TVnitrni {
  public:
    char *vnitrni2;
	TVnitrni(int input) {
		vnitrni2 = new char[input];
		for (int i=0; i<input; i++) {
			vnitrni2[i]=0;
		}
	}
	~TVnitrni() {
		delete[] vnitrni2;
	}
};

class TVnejsi {
  public:
	TVnitrni **vnejsi;
	int clenu;
	TVnejsi() {
		clenu = 10;
		vnejsi = new TVnitrni*[clenu];
		for (int i=0; i<clenu; i++) vnejsi[i] = NULL;
	}
	TVnejsi(int clen) {
		clenu = clen;
		vnejsi = new TVnitrni*[clenu];
		for (int i=0; i<clenu; i++) vnejsi[i] = NULL;
	}
	~TVnejsi() {
		for (int i=0; i<clenu; i++) if (vnejsi[i] != NULL) delete vnejsi[i];
		delete[] vnejsi;
	}
	void Zvetsi(){  // pokud nedostacuje velikost pole ukazatelu na TVnitrni, tak se zdvojnasobi
		int i;
		TVnitrni **pom;
		pom = new TVnitrni*[clenu*2];
		for (i=0; i<clenu-1; i++) pom[i] = vnejsi[i];
		for (i=clenu-1, clenu *=2; i<clenu; i++) pom[i] = NULL;
		delete vnejsi;
		vnejsi = pom;
	}
};

class THradlo {
  public:
	TVnejsi **hradlo;
	int poc_vst;
	THradlo(int pocet_vstupu) {
		poc_vst = pocet_vstupu;
		hradlo = new TVnejsi*[pocet_vstupu];
		for (int i=0; i<pocet_vstupu; i++) hradlo[i]=NULL;
	}
	~THradlo() {
		for (int i=0; i<poc_vst; i++) delete hradlo[i];
		delete[] hradlo;
	}
};

