#include "hlavicka.h"



policko Model::P_sekvencie(long sekvencia,/* int pocet_stavov,TODO pozor policko treba mazat! */
			   const Cislo* P_stavov
			   /*, 
			   Cislo** P_emisii,Cislo** P_prechodov,long* delitel,long* rad*/
			   ){
  halda sumatko;
  Cislo* pomocne_pole=new Cislo[pocet_stavov];
  for(int stav=0;stav<pocet_stavov;stav++){
    long z=sekvencia % delitel[rad[stav]];//odsekne potrebnu cast sekvencie
    Cislo q=P_emisii[stav][z];
    q=q*P_stavov[stav];
    // cerr << q.normal() << endl;
    sumatko.push(q);
    pomocne_pole[stav]=q;
  }
  Cislo spolu=sum(sumatko);
  for(int stav=0;stav<pocet_stavov;stav++){
    pomocne_pole[stav]=pomocne_pole[stav]/spolu;
  }
  halda pole_hald[pocet_stavov];
  for(int stav=0;stav<pocet_stavov;stav++){
    for(int stav2=0;stav2<pocet_stavov;stav2++){
      pole_hald[stav2].push(pomocne_pole[stav]*P_prechodov[stav][stav2]);
      //  cerr << stav << " " << stav2 << " " << Cislo(pomocne_pole[stav]*P_prechodov[stav][stav2]).normal() << endl;
    }
  }
  for(int stav=0;stav<pocet_stavov;stav++){
    pomocne_pole[stav]=sum(pole_hald[stav]);
    //cerr << "P stavu " << stav << " je " << pomocne_pole[stav].normal() << endl;
  }
  policko p(spolu,Aktual(pomocne_pole,pocet_stavov));  
  return p;
}


policko* Model::predlz(//int pocet_pismen,
		       long predchadzajuca_sekvencia,//predch_sekv
		       long pocet_stary,//pocet policok, ktory bol povodny
		       policko* stare
		       ){  
  policko* nove=new policko[pocet_stary*pocet_pismen];
  for(long pol=0;pol<pocet_stary;pol++){
    //  cerr << "policko " << pol << endl;   
    for(int pismeno=0;pismeno<pocet_pismen;pismeno++){
    //  cerr << stare[0].second.P_stavov[0].normal() << endl;
    //   cerr << "pismeno " << pismeno << "   " << pol*pocet_pismen+pismeno << endl;
      long sekvencia=(((predchadzajuca_sekvencia*pocet_stary)+pol)*pocet_pismen+pismeno);
      nove[pol*pocet_pismen+pismeno]=P_sekvencie(sekvencia,stare[pol].second.P_stavov);
    }
  }
  return nove;
}

void Model::napln(){//naplni zakladne policka
/*
Aktual* C=new Aktual(A);
Cislo d(0);
policko p(d,C);
policko e(9,C);
//delete &e;
policko r;
r=p;
e=p;
delete C;
C=new Aktual(A);
delete C;
C=new Aktual(A);
delete C;
*/

long pocet_predch;
if(max_rad>0) pocet_predch=delitel[max_rad-1];else pocet_predch=delitel[max_rad]=1; 

//pocet_predch=2;
Predpocitane=new policko**[pocet_predch];
for(long predch=0;predch<pocet_predch;predch++){
  Predpocitane[predch]=new policko*[pocet_stavov];
  for(int stav=0;stav<pocet_stavov;stav++){
    Predpocitane[predch][stav]=new policko[pocet_pismen];
    for(int pismeno=0;pismeno<pocet_pismen;pismeno++){
      Cislo* p_P_prechodov= new Cislo[pocet_stavov];
      for(int st=0;st<pocet_stavov;st++){
	p_P_prechodov[st]=P_prechodov[stav][st];
      }
      Aktual d(p_P_prechodov,pocet_stavov);
      Cislo c=Cislo(P_emisii[stav][(predch*pocet_pismen+pismeno)%delitel[rad[stav]]]);
      policko a(c,d);
      Predpocitane[predch][stav][pismeno]=a;
    }
  }
}
/*
cerr << "drdg"<< endl;
{policko p=P_sekvencie(0,A->P_stavov);
//delete &p;
}
cerr << "gjgjk" << endl;
{policko p=P_sekvencie(0,A->P_stavov);
delete &p;
}
*/

Aktual* C=new Aktual(A);
Cislo d(0);
policko p(d,*C);
policko* r;
//cerr << p.second.P_stavov[0].normal() << endl;
r=new policko(p);
delete C;
delete r;
//cerr << "wwwwwwwwwwww " << r << endl;
//cerr << &p << endl;
r=new policko[1];
r[0]=p;
//cerr << endl << endl << endl << r->second.P_stavov[0].normal() << endl << endl << endl << endl;
delete[]  r;

long predch=0;
long stav=0;
long pocet=4;
//cerr << Predpocitane[0][0][0].second.P_stavov[0].normal() << endl;
policko* pom_pole=predlz(predch,pocet,Predpocitane[predch][stav]);
//for (int i=0;i<4;i++) delete pom_pole[i];
delete[] pom_pole;

for(long predch=0;predch<pocet_predch;predch++){
  for(int stav=0;stav<pocet_stavov;stav++){
    delete[] Predpocitane[predch][stav];
  }
  delete[] Predpocitane[predch];
}
delete[] Predpocitane;
Predpocitane=0;
//delete C;

return;
}



void Model::predpocitaj(int dlzka){
  long pocet_predch;
  this->dlzka=dlzka;if(max_rad>0) pocet_predch=delitel[max_rad];else pocet_predch=delitel[max_rad]=1;//max_rad je kolko najviac predch pismen ma vplyv
  if(max_rad<dlzka-1){//zvacsi delitela co je pole s mocninami poctu_pismen
    delete[] delitel;
    delitel=new long[dlzka+1];
    delitel[0]=pocet_pismen;
    for(int i=1;i<dlzka+1;i++) delitel[i]=delitel[i-1]*pocet_pismen;
  }
  // cerr << "kontrola 1" << endl;
  
  
  //Predpocitane=new policko**[pocet_predch];
  //[pocet_stavov][pocet_pismen];
  //TODO napln to
//  napln();

Predpocitane=new policko**[pocet_predch];
cerr << "predpocitavam pre " << pocet_predch << endl;
for(long predch=0;predch<pocet_predch;predch++){
  cerr << "sekvencia: " << predch << endl;
  Predpocitane[predch]=new policko*[pocet_stavov];
  for(int stav=0;stav<pocet_stavov;stav++){
    Predpocitane[predch][stav]=new policko[pocet_pismen];
    for(int pismeno=0;pismeno<pocet_pismen;pismeno++){
      Cislo* p_P_prechodov= new Cislo[pocet_stavov];
      for(int st=0;st<pocet_stavov;st++){
	p_P_prechodov[st]=P_prechodov[stav][st];
      }
      Aktual d(p_P_prechodov,pocet_stavov);
      Cislo c=Cislo(P_emisii[stav][(predch*pocet_pismen+pismeno)%delitel[rad[stav]]]);
      policko a(c,d);
      Predpocitane[predch][stav][pismeno]=a;
    }
  }
}

  for(long predch=0;predch<pocet_predch;predch++){
    // cerr << "kontrola 2 " << predch << endl;
    cerr << "sekvencia: " << predch << endl;
    for(int stav=0;stav<pocet_stavov;stav++){
      
    
      long pocet=1;
      for(int d=1;d<dlzka;d++){
	//cerr << "mklml " << d << endl;
	//TODO vypocitaj nove policka a zmaz stare
	pocet=pocet*pocet_pismen;
	policko* pom_pole=predlz(predch,pocet,Predpocitane[predch][stav]);
	delete[] Predpocitane[predch][stav];
	Predpocitane[predch][stav]=pom_pole;
      }
    }    
  }
  cerr << "Predpocitane, hura!" << endl << endl;
  return;
}
