#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QString>
#include <QDial>
#include <QMessageBox>
#include <QFileDialog>

#include <iostream>
 #include <QToolTip>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    img_orig=NULL;
    img_pomoc=NULL;
    img_zobrazeny=NULL;
    this->size.width=100;
    this->size.height=100;
    this->size_img.width=200;
    this->size_img.height=200;
    this->posun_x=10;
    this->posun_y=10;
    this->posun_x_delta=2;
    this->posun_y_delta=2;
    this->angle=4;
    this->angle_delta=1;
    this->point_centr.x=0;
    this->point_centr.y=0;
    this->sum=0.0;

    ui->setupUi(this);
    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(Btn_load_click()));
    connect(ui->Btn_Show,SIGNAL(clicked()),this,SLOT(Btn_show_click()));
    connect(ui->Btn_make_DB_image,SIGNAL(clicked()),this,SLOT(Btn_make_DB_image_click()));


    ui->Text_width_Img->setText(QString::number(this->size_img.width));
    ui->Text_height_Img->setText(QString::number(this->size_img.height));
    ui->Text_width->setText(QString::number(size.width));
    ui->Text_height->setText(QString::number(size.height));
    ui->Text_PosunX->setText(QString::number(posun_x));
    ui->Text_PosunY->setText(QString::number(posun_y));
    ui->Text_PosunX_delta->setText(QString::number(posun_x_delta));
    ui->Text_PosunY_delta->setText(QString::number(posun_y_delta));
    ui->Text_angle->setText(QString::number(angle));
    ui->Text_angle_delta->setText(QString::number(angle_delta));
    ui->Text_Sum->setText(QString::number(sum));

   // ui->Btn_make_DB_image->setStyleSheet()
    //ui->Text_angle->setProperty("alfa", true );
    //ui->groupBox->setProperty("alfa",true);
    //this->setStyleSheet("background:green;clor:red;"  );
    //this->setStyleSheet("*[alfa='true'] { background-color: red; } ;  "  );

}

MainWindow::~MainWindow()
{
    delete ui;
    this->delete_image(&img_orig);
    this->delete_image(&img_pomoc);
    this->delete_image(&img_zobrazeny);

}

void MainWindow::delete_image(IplImage **img){
    if((*img)!=NULL)
        cvReleaseImage(img);
    //img=NULL;
}



void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}


void MainWindow::Btn_load_click(){
    this->path = QFileDialog::getOpenFileName(this, tr("Nacti obraz"),
                                                               "",
                                                               tr("Image (*.jpg *.png *.bmp);;JPEG (*.jpg *.jpeg);;PNG (*.png);;Bitmapa(*.bmp *.BMP) ;;ALL(*.*)"));

    QStringList split=path.split("/");
    dir=split.last();
    dir=dir.replace(QRegExp("\\..*$"),"");
    if(!QDir(dir).exists()){
        QMessageBox::information(this, tr("QMessageBox::information()"), "vytvarim adresar");

        if(!QDir().mkdir(dir)){
            QMessageBox::critical(this, tr("QMessageBox::critical()"), "nezdarilo se vytvorit adresar");
        }
    }
    img_orig=cvLoadImage(path.toAscii(),0);
    if(img_orig==NULL){
        QMessageBox::critical(this, tr("QMessageBox::critical()"), "Chyba načtení souboru.");
        return;
    }
//*/

}



void MainWindow::Btn_show_click(){
    if(img_orig==NULL)
        return;

    //this->show_image(img_orig);
}

void MainWindow::show_image(IplImage *img,bool show_rect,int time){
    if(img==NULL)
        return;

    this->delete_image(&(this->img_pomoc));
    this->delete_image(&(this->img_zobrazeny));

    img_zobrazeny = cvCloneImage(img);
    cvNamedWindow( "obrazek", 1) ;
    if(show_rect)cvSetMouseCallback( "obrazek",&MainWindow::my_mouse_callback_write_pixel, this);
    else cvSetMouseCallback( "obrazek",&MainWindow::my_mouse_callback_write_pixel2, this);
    cvShowImage( "obrazek", img );

    cvWaitKey(time);

    this->delete_image(&img_pomoc);
    this->delete_image(&(this->img_zobrazeny));
}


IplImage * MainWindow::Rot(IplImage* image,CvPoint2D32f centr, float angle){
    //IplImage * rotatedImage=cvCreateImage(cvSize(img_orig->width,img_orig->height),img_orig->depth,3);
    double scale=1.0;

    CvMat* affine = cvCreateMat(2,3,CV_32FC1);
    IplImage *output;
    output = cvCloneImage(image);
    output->origin = image->origin;
    cvZero(output);
    //cv2DRotationMatrix(cvPoint2D32f(image->width/2,image->height/2),angle, scale, affine);
    cv2DRotationMatrix(centr,angle, scale, affine);
    cvWarpAffine( image, output, affine);
    cvReleaseMat( &affine);

    return output;

}


IplImage * MainWindow::Roi(IplImage *image,int stredX,int stredY,int width,int height){
    CvRect rect = cvRect(stredX-(width/2),stredY-(height/2), width, height);

    IplImage* subimg=cvCreateImage(cvSize(width,height),image->depth,image->nChannels);

    cvSetImageROI(image, rect);

    cvCopy(image, subimg, NULL);

    cvResetImageROI(image);

    return subimg;
}


void MainWindow::my_mouse_callback_write_pixel(int event, int x, int y, int flags, void* param){
    MainWindow * ma=static_cast<MainWindow*>(param);
    IplImage* image = ma->img_zobrazeny;

    switch( event ){
            case CV_EVENT_LBUTTONDOWN:

                    CvScalar s;
                    s=cvGet2D(image,y,x);
                    ma->point_centr.x=x;
                    ma->point_centr.y=y;
                    std::cout<<"bod "<<x<< "x" <<y<< " hodnota "<<s.val[0]<<std::endl;//<< <<std::endl;
                    //std::cout<<"bod"<<std::endl;
                    cvDestroyWindow("obrazek");
                    break;

            case CV_EVENT_LBUTTONUP:
                    break;
            case CV_EVENT_RBUTTONUP:
                   break;
            case CV_EVENT_MOUSEMOVE:
                   ma->delete_image(&(ma->img_pomoc));
                   ma->img_pomoc = cvCloneImage(image);
                   cvRectangle( ma->img_pomoc,cvPoint(x-(ma->size.width/2),y-(ma->size.height/2)),cvPoint(x+(ma->size.width/2),y+(ma->size.height/2)), CV_RGB(255,255,255), 3, 8, 0 );
                   cvRectangle( ma->img_pomoc,cvPoint(x-(ma->size_img.width/2),y-(ma->size_img.height/2)),cvPoint(x+(ma->size_img.width/2),y+(ma->size_img.height/2)), CV_RGB(255,255,255), 3, 8, 0 );
                   cvShowImage("obrazek", ma->img_pomoc);
                   break;
    }
}

void MainWindow::my_mouse_callback_write_pixel2(int event, int x, int y, int flags, void* param){
    MainWindow * ma=static_cast<MainWindow*>(param);
    IplImage* image = ma->img_zobrazeny;
    switch( event ){
            case CV_EVENT_LBUTTONDOWN:
                    CvScalar s;
                    s=cvGet2D(image,y,x);
                    ma->point_centr.x=x;
                    ma->point_centr.y=y;
                    std::cout<<"bod "<<x<< "x" <<y<< " hodnota "<<s.val[0]<<std::endl;//<< <<std::endl;
                    //std::cout<<"bod"<<std::endl;
                    break;
            case CV_EVENT_LBUTTONUP:
                    break;
            case CV_EVENT_RBUTTONUP:
                    cvDestroyWindow("obrazek");
                   break;
            case CV_EVENT_MOUSEMOVE:

                   break;
    }
}





void MainWindow::Btn_make_DB_image_click(){
    if(img_orig==NULL)
        return;

    this->size_img.width=ui->Text_width_Img->text().toInt();
    this->size_img.height=ui->Text_height_Img->text().toInt();

    this->size.width=ui->Text_width->text().toInt();
    this->size.height=ui->Text_height->text().toInt();

    posun_x=ui->Text_PosunX->text().toInt();
    posun_y=ui->Text_PosunY->text().toInt();
    posun_x_delta=ui->Text_PosunX_delta->text().toInt();
    posun_y_delta=ui->Text_PosunY_delta->text().toInt();
    angle=ui->Text_angle->text().toInt();
    angle_delta=ui->Text_angle_delta->text().toFloat();
    sum=ui->Text_Sum->text().toDouble();


    QMessageBox::information(this, tr("QMessageBox::information()"), "Nyni vyber oblast ROI");
    this->show_image(img_orig,true);


    IplImage * rotated;
    IplImage * posun;

    posun=this->Roi(img_orig,point_centr.x,point_centr.y,size_img.width,size_img.height);
    QString p=dir+".png";
    cvSaveImage(p.toAscii(),posun);
    cvReleaseImage(&posun);

    for(int k=-1*posun_y;k<=posun_y;k+=posun_y_delta){
        for(int j=-1*posun_x;j<=posun_x;j+=posun_x_delta){

            CvPoint new_centr=cvPoint(point_centr.x+j,point_centr.y+k);

            for(float i=-1*angle;i<=angle;i+=angle_delta){

                rotated=this->Rot(img_orig,cvPoint2D32f(new_centr.x,new_centr.y),i);
                posun=this->Roi(rotated,new_centr.x,new_centr.y,size.width,size.height);
                this->Add_Noise2(posun,sum);

                    this->show_image(posun,false,50);
                    QString jmeno="zk.png";
                    jmeno=dir+"/"+QString::number(j)+";"+QString::number(k)+"r"+QString::number(i)+jmeno;
                cvSaveImage(jmeno.toAscii(), posun);
                cvReleaseImage(&posun);
                cvReleaseImage(&rotated);
             }
        }
    }



 /*   for(float i=-1*angle;i<=angle;i+=angle_delta){
        rotated=this->Rot(img_orig,cvPoint2D32f(point_centr.x,point_centr.y),i);
        this->show_image(rotated,false,300);

        QString jmeno="zk.png";
        jmeno=dir+"/"+QString::number(i)+jmeno;
        cvSaveImage(jmeno.toAscii(), rotated);
        cvReleaseImage(&rotated);
    }
  //  */

cvDestroyWindow("obrazek");

}









void MainWindow::Add_Noise2(IplImage *img,double pravdep ,float amount){
     CvSize imgSize = cvGetSize(img);

    for(int y=0;y<imgSize.height;y++)
    {
        for(int x=0;x<imgSize.width;x++)
        {
            int pixelValue = cvGetReal2D(img, y, x);

            if(pravdep >=Uniform()+0.5 ){
                double pom=Uniform();
                int randomValue = (int)(pom*amount);
                pixelValue+=randomValue;
            }
            cvSetReal2D(img, y, x, pixelValue);
      }
    }
}

double MainWindow::Uniform()
{
    return (rand()/(float)RAND_MAX)-0.5;
}

IplImage * MainWindow::Add_Noise(IplImage *image, float size){

IplImage* imgTemp = cvCloneImage(image);

//CvRNG rng= cvRNG(0x12345);
CvRNG rng= cvRNG(0x01);
IplImage* noise;

noise = cvCreateImage( cvSize(image->width, image->height), 8, image->nChannels );
cvRandArr( &rng, noise, CV_RAND_UNI, cvScalar(0,0,0),cvScalar(256,256,256));
cvAdd(imgTemp, noise, imgTemp);

this->delete_image(&noise);
return imgTemp;
}
