#ifndef _DOCOMMAND_H
#define _DOCOMMAND_H

#include <map>
#include <queue>
#include <string>

using namespace std;

class DoCommand{

    map<string,int> tranTab;      // Tabulka prechodu klic=prechod , hodnota = index                
    map<string,int> placeTab;     // Tabulka prechodu klic=misto , hodnota = index
    //iteratory
    map<string,int>::iterator itT;           
    map<string,int>::iterator itP;
    //----------------------------
    queue<string> *myfifo;       // naparsovany vstupni text
    int citacT;                  //citac signalu  + a -              
    int citac;                   //citac signalu
    Stg* stg;                    // ukazatel na structuru signal tran. graf
    int graf;                    // test zda je graf aktnivovan
    int citacP;                  //citac mist
    queue<string>  fifotm;
    queue<int>     fifotmint;   
               
public:      

      DoCommand(queue<string>* q, Stg* s){
      myfifo = q;              // prirazeni fronty v nichz je vstup
      stg = s;                 // prirazeni stg do ukazatele 
      graf = 0;                // aktivace grafu, 0 = neaktivni
      citacT = 0;              // citac signalu na nule
      citacP = 0;              // citac mist na nule
      citac = 0;               // citac signalu na nule
      
      }

//-----------------------------------------------------------------------------      
      //priprava vstupni, vystupni a internich prachodu
      void command128(int test = 0){
      
      string str;              // temp stirng
   
             
      while(!myfifo->empty()){         // dokud meni fronta odpovidajici radku prazdna
      str = myfifo->front();           // na radce jsou pojmenovane vstupni, vystupni a interni prechody 
      fifotm.push(str); fifotmint.push(test);
      str += '+';                      // kazdy prechod je v STG grafu rostouci a klesajici
      tranTab[str] = citacT++;         // vlozeni do tabulky prechodu
      str[str.size() - 1] = '-';       // kazdy prechod je v STG grafu rostouci a klesajici
      tranTab[str] = citacT++;         // vlozeni do tabulky prechodu
   
      if(test){
       
      if(!stg->pocetVyP){
      stg->vyP = new int[1];
      ++stg->pocetVyP;
      }
      else{
      int* tmpStg =  stg->vyP;
      stg->vyP = new int[++stg->pocetVyP];
      for(int fv = 0; fv < stg->pocetVyP - 1;++fv)
      stg->vyP[fv] = tmpStg[fv];
      delete tmpStg;
      } 
      
      stg->vyP[stg->pocetVyP - 1]  = citac;
      
      }  
      ++citac;                         // inkrementace poctu prechodu v grafu
      myfifo->pop();                   // odstraneni arg z fronty
      //if(!myfifo->empty()) std::cout << "chyba";
      }
      
      }

//-----------------------------------------------------------------------------      
      //pridání pocatecniho stavu do struktury
      void command3(){
      string str;
      int i = 0;     
      stg->initCode = new char[citac];                    //inicializace ve strukture                           
      stg->sizeCode = citac;                              //delka inicilayacniho kodu
      str = myfifo->front();                              
      int start = 0;
      int end;
      if(str.size() == 1){ myfifo->pop(); str = myfifo->front();}
      else{++i;}   
      if(int(str.size()) == citac) end = str.size();
      else { 
      if(str[str.size() - 1] == ']') end = str.size() - 1;
      else std::cout << "chyba";  
      }
      for(;start < citac; ++start , ++i )
      stg->initCode[start] = str[i];
      myfifo->pop();
      if(!myfifo->empty()) myfifo->pop();
      if(!myfifo->empty()) std::cout << "chyba";
      }

//-----------------------------------------------------------------------------      
      //aktivace grafu                                                                                     
      void command4(){
      graf = 1;
      if(!myfifo->empty()) std::cout << "chyba";
      }
      
     
      int tests(string str){
      for(int i = str.size() - 1;(i - 2) >= 0;--i ){
      if(str[i] >= '0' &&  str[i] <= '9'){ 
      if(str[i - 1] == '/' &&( str[i - 2] == '+' || str[i - 2] == '-' ) )
      return (i - 2);
      }
      }
      return 0;
      }

//-----------------------------------------------------------------------------      
      // hleda v tabulce existujici prechod                                                                               
      int findTran(string s){
      itT = tranTab.find(s);
      int i = itT->second;
      return i;
      }

//-----------------------------------------------------------------------------      
      // hleda v tabulce existujici misto                                                                                                                                                                    
      int findPlace(string s){
      itT = tranTab.find(s);
      int i = itT->second;
      return i;
      }

//-----------------------------------------------------------------------------      
      int stavIndex(int i){
      if((i % 2) != 0){
      --i;
      }
      return (i/2);
      }
      
//-----------------------------------------------------------------------------      
      //zpracovani grafove struktury
      void commandGraf(string str){
      string tmp;
      if(!graf) std::cout << "Neni aktivovan graf";
      int test = 1;
      int x = 0;
      int index = 0;
      if(str[str.size() - 1] == '-' || str[str.size() - 1] == '+'){
       index = findTran(str);
       stg->tran[index] = new Tran;                                //vytvoreni strktury prechodu
       (stg->tran[index])->stavInd = stavIndex(index);             // prideleni indexu
      (stg->tran[index])->riseOrFall = str[str.size() - 1];        //prideleni + -
      (stg->tran[index])->numOfip = myfifo->size();                
      (stg->tran[index])->indexPlace = new int[myfifo->size()];    // index place
      while(!myfifo->empty()){
      tmp = myfifo->front();
      stg->place[citacP] = new Place;                             // vytvoreni mist    
      (stg->place[citacP])->token = '0';                          //token
      (stg->place[citacP])->indexTran = findTran(tmp);            //iondex na prechody
      (stg->tran[index])->indexPlace[x++] = citacP; 
      ++citacP;
      myfifo->pop();
      }
      test = 0;
      }
      if(tests(str)) cout << "vice prechodu";
      if(test)      cout << "place";
      
      
      }

//-----------------------------------------------------------------------------      
      // prida tokeny                                                                                     
      void marking(string s){
      size_t f = s.find(',');
      string tmp = s.substr(0,f); 
      string tmp2 = s.substr(f+1,s.size()-1);
      int pos = findTran(tmp);
      int pos2 = findTran(tmp2);
      for(int i = 0; i < (stg->tran[pos])->numOfip;i++)
      
      if((stg->place[(stg->tran[pos])->indexPlace[i]])->indexTran == pos2)
      (stg->place[(stg->tran[pos])->indexPlace[i]])->token = '1';
      }

//-----------------------------------------------------------------------------      
      // doplneni informaci o celkavem grafu
      void command6(){

      while(!fifotm.empty()){
      stg->nazvy.push_back(fifotm.front());
      stg->nazvyp.push_back(fifotmint.front());
      fifotm.pop();
      fifotmint.pop();
      }     
      
      stg->pocetPlace = citacP;
      stg->pocetTran = citacT;
      }

//-----------------------------------------------------------------------------      
      // projde STG place a prida tokeny 
      void command5(){
      if(!graf) cout << "chyba";
           
      string str = myfifo->front();
      int pos = 0;
      size_t found;
      size_t found2;
      while(!myfifo->empty()){
      
      while(1){
      found = str.find('<',pos);
      if(found != string::npos){
      if((found2 = str.find('>')) != string::npos)
      {pos = found2 + 1; 
      marking(str.substr(found + 1,(found2 - found) - 1));}
      else break;
      }
      else break;
      }
      pos = 0;
      myfifo->pop();
      if(!myfifo->empty())
      str = myfifo->front();
      }
      
      }

//-----------------------------------------------------------------------------      
      //jmeno vystupniho souboru vlozeni do STG
      void commandName() {
      stg->nameFile = myfifo->front();
      }

};

#endif
