#include "ris.h"



ris::ris(my_image *img, int pocet, int delka,bool modd)
{
    this->ri=NULL;
    this->ri_ref=NULL;
    this->img=NULL;
    this->img_ref=NULL;
    this->count_ri=0;
    this->count_ri_ref=0;

    this->mod=modd;
    this->count_l=pocet;//pocet primek
    this->length=delka;

    std::cout<<"pocet primek je "<<this->count_l<<" velikost primek je "<<this->length<<"\n";
    std::cout<<"delta uhlu bude tedy "<< (2*PI)/this->count_l<<" radianu \n";

    this->img_ref=new my_image(img);
    if(!this->mod){
        std::cout<<"budu pocitat RIS prostor \n";
        this->ri_ref=this->img2RI(this->img_ref,&this->count_ri_ref);
    }
    else std::cout<<"konstruktor RIS dokoncen \n";
}

ris::~ris()
{
    if(this->img_ref!=NULL)
        delete this->img_ref;
    if(this->ri_ref!=NULL){
        for(int i=0;i<this->count_ri_ref;i++)
             delete this->ri_ref[i];
        delete []this->ri_ref;
    }

    this->del_img();
}



ris::RI* ris::point2RI(int x, int y, my_image *img){
    ris::RI * ris =new ris::RI();
    ris->x = x;
    ris->y = y;
    if(this->count_l<1){
        std::cout<<"pocet primek je prilis maly \n";
    }

    float delata_angle=(2*PI)/this->count_l;
    int x2;
    int y2;

    //!!!!!!!!
    int j=0;
    for (float i = 0; j <this->count_l ; i +=delata_angle)
    {
        float p;
        p=cos(i);
        x2=x+((float)this->length*p);
        p=sin(i);
        y2=y+((float)this->length*p);
        ris->sum.push_back(RI_l(img, x, y,x2,y2));
        j++;
    }

    return ris;
}


int ris::RI_l(my_image * image,int x0, int y0, int x1,int y1)//vypocita sumu bodu na kedne primce
  {
    int sum=0;

    int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
    int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
    int err = (dx>dy ? dx : -dy)/2, e2;

    for(;;){
     sum+=get_pixel(x0,y0,image);// draw_pixel(x0, y0);
      if (x0==x1 && y0==y1) break;
      e2 = err;
      if (e2 >-dx) { err -= dy; x0 += sx; }
      if (e2 < dy) { err += dx; y0 += sy; }
    }

 return sum;
  }//do_CIS_r

int ris::get_pixel(int x, int y, my_image *image){
     uchar g=image->get( x,y);
    //image->set(x,y,255);
    if(g<128)
        return 1;
    else
        return 0;
}

ris::RI ** ris::img2RI(my_image *img,int* count){
   //inicializace promenne ref_ri
    int count_rii=(img->Width()-(2*this->length))*(img->Height()-(2*this->length));//tolik jich teoreticky bude

    ris::RI **ret_ri; // a pointer to a pointer to an object from the "toy" class

    ret_ri = new ris::RI *[count_rii]; // use as an array of 33 pointers to "toy" objects

    int k=0;
    for (int i = this->length; i < img->Width()-(this->length+1); i++)
    {
        for (int j = this->length; j < img->Height()-(this->length+1); j++)
        {
            if((*count)>=count_rii){
                std::cout<<"NEJVETSI CHYBA VSECH CHYB\n";
                throw "cccccc";
            }
            ret_ri[k] =this->point2RI(i,j,img); //kazdymu k alokuju misto
            (*count)++;
            k++;
        }
    }
/*
 std::cout<<"RI jsem spocital pro "<<(*count)<<"bodu\n";
 for(int i=0;i<(*count);i++){
     std::cout<<"\nRI_ref"<<i<<" x"<<ret_ri[i]->x<<" y "<<ret_ri[i]->y<<"\t sum ";
     for (int j=0;j<this->count_l;j++)
         std::cout<<" x "<<j<<"=>"<<ret_ri[i]->sum[j];
 }
//*/

 return ret_ri;
}


bool ris::find(my_image *img){
    if(this->mod){
        std::cout<<"ris mod je zapnut na true -> pouzij find pro body\n";
        return false;
    }

    this->del_img();//kdyby byl jiz nejaky obraz nacten tak  ho vymaz

    this->img=new my_image(img);//uloz obraz

    this->ri=new ris::RI *[1];//pocitam pouze pro jeden bod
    int stred_x=this->img->Width()/2;
    int stred_y=this->img->Height()/2;
    this->ri[0]=this->point2RI(stred_x,stred_y,this->img);
    std::cout<<"obraz ma souradnice "<<stred_x<<"  "<<stred_y<<"\n";
    for(int i=0;i<this->count_l;i++)
        std::cout<<"integral obrazu na kruhu "<<i<<" je "<<this->ri[0]->sum[i]<<"\n";
//*/
    //picitam diferenci
    for (int i=0;i<this->count_ri_ref;i++){
        int dif=(*this->ri[0])-(*this->ri_ref[i]);
      //  std::cout<<i<<" diference pro bod x "<<this->ri_ref[i]->x<<" y "<<this->ri_ref[i]->y<<"  je"<<dif<<"\n";
       this->body.push_back(BOD((this->ri_ref[i]->x),this->ri_ref[i]->y,dif));
    }

    std::cout<<"v referencnim obraze je suma "<<this->ri_ref[1]->sum[0]<<" a v nactenem je "<<this->ri[0]->sum[0]<<"\n";


    std::sort(this->body.begin(),this->body.end());
    return true;
}


bool ris::find(my_image *img,std::vector<BOD> candidats)//pokud je RIS mod v true->pouzi pro find tuto metodu -> body ve vektoru jsou kandidati
{
    if(! this->mod){
        std::cout<<"ris mod je vypnut  -> pouzij radej find pro cely obraz, ale pokracju pouze s uvedenymi body\n";
    }
    this->del_img();//kdyby byl jiz nejaky obraz nacten tak  ho vymaz

    this->img=new my_image(img);//uloz obraz

    this->ri=new ris::RI *[1];//pocitam pouze pro jeden bod
    int stred_x=this->img->Width()/2;
    int stred_y=this->img->Height()/2;
    this->ri[0]=this->point2RI(stred_x,stred_y,this->img);
    std::cout<<"obraz ma souradnice "<<stred_x<<"  "<<stred_y<<"\n";
    for(int i=0;i<this->count_l;i++)
        std::cout<<"integral obrazu na kruhu "<<i<<" je "<<this->ri[0]->sum[i]<<"\n";
//*/
    //picitam diferenci
    int dif;
     ris::RI * temp;
    for (int i=0;i<candidats.size();i++){
        temp=new ris::RI();
        temp=this->point2RI(candidats[i].x ,candidats[i].y,this->img_ref );
        dif=(*this->ri[0])-(*temp);
      //  std::cout<<i<<" diference pro bod x "<<this->ri_ref[i]->x<<" y "<<this->ri_ref[i]->y<<"  je"<<dif<<"\n";
       this->body.push_back(BOD(candidats[i].x,candidats[i].y,dif));
       delete temp;
    }




    std::sort(this->body.begin(),this->body.end());
    return true;
}



void ris::del_img(){
    if(this->img!=NULL)
        delete this->img;
    if(this->ri!=NULL){
        for(int i=0;i<this->count_ri;i++)
            delete this->ri[i];
        delete []this->ri;
    }
    this->count_ri=0;
    this->body.erase(body.begin(),body.end());
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////PODPŮRNA TŘÍDA RI////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////// KAZDA INSTANCE REPREZENTUJE JEDEN BOD  RIS VZDALENOSTI//////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////


ris::RI::RI()
{
    //std::cout<<"konstruktor CI \n";
    this->x = 0;
    this->y = 0;
   // this->sum = new double[count];
 //   this->count_l = count;
}

ris::RI::~RI(){
    //std::cout<<"destruktor RI \n";
    this->sum.erase(this->sum.begin(),this->sum.end());
    //delete []this->sum;
}


int ris::RI::operator-(const ris::RI &t1) const
{
    int dif_m = 99999 ;
    int dif;
    if (t1.sum.size() != (*this).sum.size()) std::cout<<"ERROR !!!\n pole nemaji stejnou delku!! -funkce ris::RI operator - \n";


std::vector<int> faf;
std::vector<int> kaf;
faf=this->sum;
kaf=t1.sum;

std::vector<int>::iterator temp,temp2;
//std::vector<int>::iterator temp2= this->sum.begin();

for(int i=0;i<faf.size();i++){
    dif=0;
    for(temp = faf.begin(),temp2=kaf.begin();temp != faf.end(); temp++,temp2++)
    {
        dif+= abs((*temp) - (*temp2));
    }
    if(dif<dif_m)
        dif_m=dif;
    std::rotate(faf.begin(),faf.begin()+1,faf.end());
}



//*/

//std::cout<<"dference je "<<dif_m<<"\n";




    return dif_m;
}
