#ifndef _CELEM_H
#define _CELEM_H


#include <vector>
#include <string>
#include <queue>
#include <fstream>

using namespace std;

struct Celem{
int posPr;     //pozice prechodu
string set;    //set C
string reset;  //reset C
};

struct Cbuffer{

vector<Celem> vect;       
       
};


class MakeCorLog{

Cbuffer* cb;
Stg* stg;
queue<string> set;
queue<string> reset;
string body;
string signaly;
string entit;
fstream is; 

public:      

MakeCorLog(Cbuffer* c,Stg* st){
stg = st;
if(stg->nameFile.empty()) stg->nameFile = "tmp";    //pokud neni jmeno nastavi difaultni
stg->nameFile += ".vhd";
is.open( stg->nameFile.c_str() , fstream::out);
cb = c;

makeCorLog();
}

~MakeCorLog(){
is.close();
}


//-----------------------------------------------------------------------------      
// sklada podle setu a resetu vhdl kod
void makeVHDL(string out){
int test = 0;
if(set.empty()) test = 1;
if(reset.empty()) test = 2;

// vhdl pro portovani c-elem
if(!test){
string tmp1 = out;
string tmp2 = out;
tmp1 += "S";
tmp2 += "R";


signaly += "signal "; signaly += tmp1; signaly += " : STD_LOGIC;\n";
signaly += "signal "; signaly += tmp2; signaly += " : STD_LOGIC;\n";

body += out;body += "CM "; body += ": "; body += "cm\n";
body +=  "port map ( "; body += tmp1;body += " , ";
body += tmp2; body += " , " ;body +=  out;body += " );\n"; 

tmp1 += " <= ";

while(!set.empty()){
tmp1 += set.front();
set.pop();
if(!set.empty())
tmp1 += " and ";
}
tmp1 += " ;\n";

out = tmp1;

tmp2 += " <= ";

while(!reset.empty()){
tmp2 += reset.front();
reset.pop();
if(!reset.empty())
tmp2 += " and ";
}
tmp2 += " ;\n";
out += tmp2;
}     

//-------------------------------------------------
// bez c-elementu
if(test == 1){
out += "<= ";
while(!reset.empty()){
out += reset.front();
reset.pop();
if(!reset.empty())
out += " and ";
}
out+= " ;\n";
}

//---------------------------------------------------
// bez c-elementu
if(test == 2){
out += "<= ";
while(!set.empty()){
out += set.front();
set.pop();
if(!set.empty())
out += " and ";
}
out+= " ;\n";
}

body += out;

}


//-----------------------------------------------------------------------------      
//uvod vhdl vstupni signaly apod.
void makeCorLog(){

int test = 0;
int test2 = 0;
is << "library IEEE;\nuse IEEE.STD_LOGIC_1164.ALL;\nuse IEEE.STD_LOGIC_ARITH.ALL;\nuse IEEE.STD_LOGIC_UNSIGNED.ALL;\n";
is << "entity " << stg->nameFile << " is\n Port ( ";

for(int i = 0; i < int(stg->nazvyp.size());i++){
signaly += "signal "; signaly += stg->nazvy[i]; signaly += " : STD_LOGIC;\n";

if(stg->nazvyp[i] == 0) {
entit +=  "in"; entit +=  stg->nazvy[i]; entit +=  ": in STD_LOGIC;\n";
body += stg->nazvy[i]; body += " <= "; body += "in"; body += stg->nazvy[i];body+= ";\n";
}

if(stg->nazvyp[i] == 1) {
entit +=  "out"; entit +=  stg->nazvy[i]; entit +=  ": out STD_LOGIC;\n";
body += "out"; body += stg->nazvy[i]; body += " <= ";  body += stg->nazvy[i]; body+= ";\n"; 
}

}
entit[entit.size() - 2] = ' ';
is << entit;
is << " );\n end " << stg->nameFile << ";" <<endl << "\narchitecture Behavioral of " << stg->nameFile << " is " ;

is << "\ncomponent cm\n";
is <<   "Port ( S : in  STD_LOGIC;\n";
is <<          "R : in  STD_LOGIC;\n";
is <<          "out_c : out  STD_LOGIC);\n";
is <<  "end component;\n";


for(int i = 0; i < int(cb->vect.size());++i){

if( cb->vect[i].set[cb->vect[i].posPr] == '-' &&
cb->vect[i].reset[cb->vect[i].posPr] == '-')
test = 1;


for(int j = 0;j < int(stg->sizeCode);j++ ){



if(j != cb->vect[i].posPr ){

if(cb->vect[i].set[j] == '1')
{if(test) test2 = 1;

set.push(stg->nazvy[j]);
}

if(cb->vect[i].set[j] == '0')
{if(test) test2 = 1;
string stmp = "(not ";
stmp += stg->nazvy[j];
stmp += ")";
set.push(stmp );

}

if(cb->vect[i].reset[j] == '1'){
if(!test2){
reset.push(stg->nazvy[j]);
}
}

if(cb->vect[i].reset[j] == '0'){
if(!test2){
string stmp = "(not ";
stmp += stg->nazvy[j];
stmp += ")";
reset.push(stmp);

}
}
test2 = 0;
}

}

 

 

makeVHDL(stg->nazvy[cb->vect[i].posPr]);



test = 0;

}

is << signaly;
is <<  "begin\n";
is << body;
is << "\nend Behavioral;" ;

}



};


#endif
