// KSim.cpp 
//Vytvoril Karel Houzvicka jako bakalarskou praci na CVUT FEL 2010

#include "../BOOM/stdafx.h"
#include <string>
using namespace std;
#include "../../Kernel/kernelincludes.h"

//Bitove pole DC  1,0 -> 1 ; '-' -> 0 
//Prevede string na bitvector
bitvector iTermToBitDC(string IM){
	int i;
	bitvector out(IM.length());
	for(i=IM.length()-1;i>=0;i--){
		if(IM.c_str()[i]=='1'||IM.c_str()[i]=='0'){
			out.setbit(i,1);
		}
	}
	return out;
}
//bitove pole 1, '-' -> 0 
//Prevede string na bitvector
bitvector iTermToBit(string IM){
	int i;
	bitvector out(IM.length());
	for(i=IM.length()-1;i>=0;i--){
		if(IM.c_str()[i]=='1'){
			out.setbit(i,1);
		}
	}
	return out;
}
/*spoji dva OM
		~11
		0~~
	=	011	
	*/
string appendStringOut(string a,string b, PLA_type type){
	unsigned int i;
	string out="";
	if (a.length()==0){return b;}
	if (b.length()==0){return a;}
	for(i=0;i<a.length();i++){
		if(	a.c_str()[i]=='~'){
			out=out+b.c_str()[i];
			continue;
		}
		if(	b.c_str()[i]=='~'){
			out=out+a.c_str()[i];
			continue;
		}
		//oba maji stejnou, tak se zachova
		if(	b.c_str()[i]==a.c_str()[i]){
			out=out+a.c_str()[i];
			continue;
		}
		//kdyz fd a na vystupu je 1 a '-' -> '-'
		if(type.f&&type.d){
			if((a.c_str()[i]=='1'&& b.c_str()[i]=='-')||(a.c_str()[i]=='-'&& b.c_str()[i]=='1')){
				out=out+'-';
				continue;
			}
		}

		//pokud maji jinou, tak chyba.
		throw IOException( "Bad  PLA file: " + a+" "+b );

	}
	return out;

}

//upravi vystupni string, odstrani z nej ~
//										pozadovana velikost vystupu
string setOut(string in, PLA_type type, int length){
	unsigned int i;
	char doplnek;
	string out="";
	int value= 100*(type.f)+10*(type.r)+(type.d);
		switch (value){
			case 10:
			case 11: {
					doplnek='1';
					break;
					}
		  	case 100: 
			case 101:{
					doplnek='0';
					break;
					}
			case 110:{
					doplnek='-';
					break;
					}		
		}
		if(in.length()!=length){	//kdyz je in prazdny
			for(int j=0;j<length;j++){
				out=out+doplnek;
			}
		
		return out;
		}
		for(i=0;i<in.length();i++){
			if(in.c_str()[i]=='~') {
				out=out+doplnek;
				continue;
			}
			out=out+in.c_str()[i];
		}
	return out;
}

//simulace PLA
string bitSimul(PLA & vstupPLA, string iStr){
// predpokladam validni vstup
	list<Term> * lTerm;
	list<Term>::iterator iter;
	lTerm = vstupPLA.GetData();	
	string out="";
	bitvector iBit;
	iBit= iTermToBit(iStr);
	for(iter=lTerm->begin();iter!=lTerm->end();iter++){
		//DC&IN==IM
		if(	((iTermToBitDC((*iter).GetIM()))&iBit)==iTermToBit((*iter).GetIM())){
			out=appendStringOut(out,(*iter).GetOM(),vstupPLA.GetType());
		}
	}

	out= setOut(out,vstupPLA.GetType(),lTerm->front().GetOM().length());
	return out;
}



int main(int argc, char* argv[])
{
	list<Term> * lTerm;
	list<Term>::iterator iter;
	PLA_type vstup_type;
	
	char  s_char[50];
	string iStr;
	PLA vstup;
	unsigned int i;
	cout<<"KSim, program na simulaci obvodu PLA."<<endl;
	cout<<"Vytvoril Karel Houzvicka, jako bakalarskou praci na CVUT FEL roku 2010."<<endl<<endl;
	cout<<"Test PLA"<<endl<<"Soubor:"<<endl;
	cin.getline(s_char,50);
	
	try{
		vstup.LoadPLA(s_char);
    }
	catch (IOException e){
		cout<<"Chyba v nacitani PLA."<<endl;
		return 0;
	}
	cout<<"soubor: "<<s_char<<endl;
	vstup_type = vstup.GetType();
	lTerm = vstup.GetData();
	//vypis
	
	cout<<"typ PLA: f"<<vstup_type.f<<" d"<<vstup_type.d<<" r"<<vstup_type.r<<endl;
	for(iter=lTerm->begin();iter!=lTerm->end();iter++){
		cout << (*iter).GetIM() << " "<<(*iter).GetOM()<<endl;;
	}

	cout<<endl<<"Zadejte vstup:"<<endl;
	 while (getline(cin, iStr)) {	
			if(iStr.length()!=lTerm->front().GetIM().length()){
				cout<<"Spatna velikost vstupu. Pozadovana velikost: "<<lTerm->front().GetIM().length()<<endl;
				return 0;
			}
			//test korektnosti vstupu
			for(i=0;i<iStr.length();i++){
				if(!(iStr.c_str()[i]=='0'||iStr.c_str()[i]=='1')){
					cout<<"Spatne znaky na vstupu: "<<iStr.c_str()[i]<<endl;
					return 0;
				}
			}
			try{
				cout<<"Vystup: "<<bitSimul(vstup,iStr)<<endl;
			}catch(IOException){
				cout<<"Konflikt PLA."<<endl;
				}
			 }
	cout<<"To je konec."<<endl;
	return 0;
}
