#include "cis.h"




cis::cis(my_image * img,int circle_cound,int circle_delta)
{
    this->ci=NULL;
    this->ci_ref=NULL;
    this->img=NULL;
    this->img_ref=NULL;
    this->count_ci=0;
    this->count_ci_ref=0;


    this->count_r=circle_cound;//pocet kruznic
    this->delta_r=circle_delta;
    this->min_r=2;


    this->img_ref=new my_image(img);
    std::cout<<"konstruktor CIS -> jdu pocitat CIS prostor \n";
    this->ci_ref=this->img2CI(this->img_ref,&this->count_ci_ref);



    std::cout<<"pocet kruznic je "<<this->count_r<< " vzdalenost mezi kruznicemi je "<<this->delta_r<<"\n";
    std::cout<<"konstruktor CIS dokoncen \n";
}


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

    this->del_img();
}



cis::CI* cis::point2CI(int x, int y, my_image *img){
    cis::CI * cis =new cis::CI(this->count_r);
    cis->x = x;
    cis->y = y;
    if(this->count_r<1){
        std::cout<<"polomer je prilis maly \n";
    }

    for (int i = 0; i < this->count_r; i ++)
    {
        cis->sum[i] = CI_r(img, x, y, min_r+(i*delta_r));
    }

    return cis;
}


double cis::CI_r(my_image * image,int x0, int y0, int radius)//vypocita sumu bodu na jednom radiusu
  {
      double sum = 0;
      int f = 1 - radius;
      int ddF_x = 1;
      int ddF_y = -2 * radius;
      int x = 0;
      int y = radius;

      sum += this->get_pixel(x0, y0 + radius,image);
      sum += this->get_pixel( x0, y0 - radius,image);
      sum += this->get_pixel( x0 + radius, y0,image);
      sum += this->get_pixel( x0 - radius, y0,image);

      while (x < y)
      {
          // ddF_x == 2 * x + 1;
          // ddF_y == -2 * y;
          // f == x*x + y*y - radius*radius + 2*x - y + 1;
          if (f >= 0)
          {
              y--;
              ddF_y += 2;
              f += ddF_y;
          }
          x++;
          ddF_x += 2;
          f += ddF_x;
          sum += this->get_pixel( x0 + x, y0 + y,image);
          sum += this->get_pixel( x0 - x, y0 + y,image);
          sum += this->get_pixel( x0 + x, y0 - y,image);
          sum += this->get_pixel( x0 - x, y0 - y,image);
          sum += this->get_pixel( x0 + y, y0 + x,image);
          sum += this->get_pixel( x0 - y, y0 + x,image);
          sum += this->get_pixel( x0 + y, y0 - x,image);
          sum += this->get_pixel( x0 - y, y0 - x,image);
      }
 return sum;
  }//do_CIS_r

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

cis::CI ** cis::img2CI(my_image *img,int* count){
   //inicializace promenne ref_ci
    int max_r=this->min_r+(this->delta_r*(this->count_r-1));
    int count_cii=(img->Width()-(2*max_r))*(img->Height()-(2*max_r));//tolik jich teoreticky bude



    cis::CI **ret_ci; // a pointer to a pointer to an object from the "toy" class

    ret_ci = new cis::CI *[count_cii]; // use as an array of 33 pointers to "toy" objects

    int k=0;
    for (int i = max_r; i < img->Width()-(max_r+1); i++)
    {
        for (int j = max_r; j < img->Height()-(max_r+1); j++)
        {
            if((*count)>=count_cii){
                std::cout<<"NEJVETSI CHYBA VSECH CHYB\n";
                throw "cccccc";
            }
            ret_ci[k] =this->point2CI(i,j,img); //kazdymu k alokuju misto
            (*count)++;
            k++;
        }
    }
/*
 std::cout<<"CI jsem spocital pro "<<(*count)<<"bodu\n";
 for(int i=0;i<(*count);i++){
     std::cout<<"\nCI_ref"<<i<<" x"<<ret_ci[i]->x<<" y "<<ret_ci[i]->y<<"\t sum ";
     for (int j=0;j<this->count_r;j++)
         std::cout<<" x "<<j<<"=>"<<ret_ci[i]->sum[j];
 }
//*/

 return ret_ci;
}


bool cis::find(my_image *img){
    this->del_img();//kdyby byl jiz nejaky obraz nacten tak  ho vymaz

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


    this->ci=new cis::CI *[1];//pocitam pouze pro jeden bod
    int stred_x=this->img->Width()/2;
    int stred_y=this->img->Height()/2;

    //kontrola zda je prichozi obraz tak velky aby se do nej vesli kruznice
    if(((this->count_r*this->delta_r)+this->min_r+stred_x)>=this->img->Width() || ((this->count_r*this->delta_r)+this->min_r+stred_y)>=this->img->Height() ){
        std::cout<<"vstupni obraz je prilis maly abych do nej vykreslil vsechny kruznice \n rozmery obrazu jsou:"<<img->Width()<<" x "<< img->Height()<<" maximalni kruznice ma vsak polomer"<< (this->count_r*this->delta_r)+this->min_r+stred_x << "\ntakze KONCIM \n"<<std::endl;
        return false;
    }


    this->ci[0]=this->point2CI(stred_x,stred_y,this->img);
/*    std::cout<<"obraz ma souradnice "<<stred_x<<"  "<<stred_y<<"\n";
    for(int i=0;i<this->count_r;i++)
        std::cout<<"integral obrazu na kruhu "<<i<<" je "<<this->ci[0]->sum[i]<<"\n";
//*/


    //picitam diferenci
    for (int i=0;i<this->count_ci_ref;i++){
        int dif=(*this->ci[0])-(*this->ci_ref[i]);
//        std::cout<<i<<" diference pro bod x "<<this->ci_ref[i]->x<<" y "<<this->ci_ref[i]->y<<"  je"<<dif<<"\n";
       this->body.push_back(BOD((this->ci_ref[i]->x),this->ci_ref[i]->y,dif));
    }

    std::cout<<"v referencnim obraze je suma "<<this->ci_ref[1]->sum[0]<<" ale v nactenem je "<<this->ci[0]->sum[0]<<"\n";


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



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

////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////PODPŮRNA TŘÍDA CI////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////// KAZDA INSTANCE REPREZENTUJE JEDEN BOD  CIS VZDALENOSTI//////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////


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

cis::CI::~CI(){
    //std::cout<<"destruktor CI \n";
    delete []this->sum;
}


int cis::CI::operator-(const cis::CI &t1) const
{
    int dif = 0 ;
    if (t1.count_r != (*this).count_r) std::cout<<"ERROR !!!\n pole nemaji stejnou delku!! -funkce cis:CCIS operator - \n";

    for (int i = 0; i < t1.count_r; i++){
        dif += abs(t1.sum[i] - (*this).sum[i]);
        //std::cout<<"operator "-" pro radius "<<i<<" jsou hodnoty sumy "<< t1.sum[i]<< " x" <<(*this).sum[i]<<" celkova dif je" <<dif<<"\n";
    }
    return dif;
}
