#include <QtGui>

 #include "mainwindow.h"

 MainWindow::MainWindow()
 {
     window = new QWidget;
     tabWidget = new QTabWidget;
     textEdit = new QPlainTextEdit;
     labelIm = new QLabel;

     contrast = new QWidget;
     filtration = new QWidget;
     geotransformation = new QWidget;

     //contrast

     lc0 = new QVBoxLayout;
     lc1 = new QHBoxLayout;
     lc2 = new QHBoxLayout;
     spinBoxC1 = new QSpinBox;
     sliderC1 = new QSlider(Qt::Horizontal);
     spinBoxC1->setRange(0, 130);
     sliderC1->setRange(0, 130);
     QObject::connect(spinBoxC1, SIGNAL(valueChanged(int)),
     sliderC1, SLOT(setValue(int)));
     QObject::connect(sliderC1, SIGNAL(valueChanged(int)),
     spinBoxC1, SLOT(setValue(int)));
     spinBoxC1->setValue(35);
     QLabel *labelC1 = new QLabel("Linear Extension   ");
     lc1->addWidget(labelC1);
     lc1->addWidget(spinBoxC1);
     lc1->addWidget(sliderC1);

     spinBoxC2 = new QSpinBox;
     sliderC2 = new QSlider(Qt::Horizontal);
     spinBoxC2->setRange(0, 130);
     sliderC2->setRange(0, 130);
     QObject::connect(spinBoxC2, SIGNAL(valueChanged(int)),
     sliderC2, SLOT(setValue(int)));
     QObject::connect(sliderC2, SIGNAL(valueChanged(int)),
     spinBoxC2, SLOT(setValue(int)));
     spinBoxC2->setValue(30);
     QLabel *labelC2 = new QLabel("Channel Extension");
     lc2->addWidget(labelC2);
     lc2->addWidget(spinBoxC2);
     lc2->addWidget(sliderC2);

     lc0->addLayout(lc1);
     lc0->addLayout(lc2);
     contrast->setLayout(lc0);

     // filtration

     lf0 = new QVBoxLayout;
     lf1 = new QHBoxLayout;
     lf2 = new QHBoxLayout;
     spinBoxF1 = new QSpinBox;
     sliderF1 = new QSlider(Qt::Horizontal);
     spinBoxF1->setRange(0, 130);
     sliderF1->setRange(0, 130);
     QObject::connect(spinBoxF1, SIGNAL(valueChanged(int)),
     sliderF1, SLOT(setValue(int)));
     QObject::connect(sliderF1, SIGNAL(valueChanged(int)),
     spinBoxF1, SLOT(setValue(int)));
     spinBoxF1->setValue(35);
     QLabel *labelF1 = new QLabel("Gaussian Filter");
     lf1->addWidget(labelF1);
     lf1->addWidget(spinBoxF1);
     lf1->addWidget(sliderF1);

     spinBoxF2 = new QSpinBox;
     sliderF2 = new QSlider(Qt::Horizontal);
     spinBoxF2->setRange(0, 130);
     sliderF2->setRange(0, 130);
     QObject::connect(spinBoxF2, SIGNAL(valueChanged(int)),
     sliderF2, SLOT(setValue(int)));
     QObject::connect(sliderF2, SIGNAL(valueChanged(int)),
     spinBoxF2, SLOT(setValue(int)));
     spinBoxF2->setValue(30);
     QLabel *labelF2 = new QLabel("Harshness       ");
     lf2->addWidget(labelF2);
     lf2->addWidget(spinBoxF2);
     lf2->addWidget(sliderF2);

     lf0->addLayout(lf1);
     lf0->addLayout(lf2);
     filtration->setLayout(lf0);

     // geotransformation

     lg0 = new QVBoxLayout;
     lg1 = new QHBoxLayout;
     lg2 = new QHBoxLayout;
     spinBoxG1 = new QSpinBox;
     sliderG1 = new QSlider(Qt::Horizontal);
     spinBoxG1->setRange(-180,180);
     sliderG1->setRange(-180,180);
     QObject::connect(spinBoxG1, SIGNAL(valueChanged(int)),
     sliderG1, SLOT(setValue(int)));
     QObject::connect(sliderG1, SIGNAL(valueChanged(int)),
     spinBoxG1, SLOT(setValue(int)));
     spinBoxG1->setSuffix("'");
     spinBoxG1->setValue(0);
     QLabel *labelG1 = new QLabel("Rotation");
     lg1->addWidget(labelG1);
     lg1->addWidget(spinBoxG1);
     lg1->addWidget(sliderG1);

     spinBoxG2 = new QSpinBox;
     sliderG2 = new QSlider(Qt::Horizontal);
     spinBoxG2->setRange(1, 1000);
     sliderG2->setRange(1, 1000);
     QObject::connect(spinBoxG2, SIGNAL(valueChanged(int)),
     sliderG2, SLOT(setValue(int)));
     QObject::connect(sliderG2, SIGNAL(valueChanged(int)),
     spinBoxG2, SLOT(setValue(int)));
     spinBoxG2->setSuffix("%");
     spinBoxG2->setValue(100);
     QLabel *labelG2 = new QLabel("Zoom     ");
     lg2->addWidget(labelG2);
     lg2->addWidget(spinBoxG2);
     lg2->addWidget(sliderG2);

     lg0->addLayout(lg1);
     lg0->addLayout(lg2);
     geotransformation->setLayout(lg0);

     //gsg

     tabWidget->addTab(contrast,"Contrast");
     tabWidget->addTab(filtration,"Filtration");
     tabWidget->addTab(geotransformation,"Geometric Transformation");
     tabWidget->showMinimized();
     mainLayout = new QVBoxLayout;
     mainLayout->setSizeConstraint(QLayout::SetMinimumSize);
     mainLayout->addWidget(labelIm);
     mainLayout->addWidget(tabWidget);
     window->setLayout(mainLayout);
     setCentralWidget(window);

     createActions();
     createMenus();
     createStatusBar();

     setUnifiedTitleAndToolBarOnMac(true);
 }

 void MainWindow::openIm()
 {
     //if (maybeSave()) {
         QString fileName = QFileDialog::getOpenFileName(this);
         if (!fileName.isEmpty())
         {
            //delete image;
            //delete curImage;
            image = new QPixmap;
            image->load(fileName);
            labelIm->setPixmap(*image);
            curFile = fileName;
            curImage=new QImage(image->toImage());
            labelIm->setMinimumSize(curImage->width(), curImage->height());
            if ((image->width()) > 512)
                {
                int p =  51200 / (float)(image->width());
                zoom(p);
                }
            isModified = false;
            koefp = 100;
            koefg = 0;
            spinBoxG2->setValue(100);
            spinBoxG1->setValue(0);
            repaint();
            statusBar()->showMessage(tr("Image Opened"), 2000);

     }
 }

 bool MainWindow::saveIm()
 {
     if (curFile.isEmpty()) {
         return saveImAs();
     } else
     {
         QFile file(curFile);
         file.open(QFile::WriteOnly);
         (labelIm->pixmap())->save(curFile);

         statusBar()->showMessage(tr("Image Saved"), 2000);
         isModified = false;
         return true;//saveFile(fileName);
     }
 }

 bool MainWindow::saveImAs()
 {
     QString fileName = QFileDialog::getSaveFileName(this);
     if (fileName.isEmpty())
         return false;
     QFile file(fileName);
     file.open(QFile::WriteOnly);
     (labelIm->pixmap())->save(fileName);

     statusBar()->showMessage(tr("Image Saved Ass"), 2000);
     isModified = false;
     return true;//saveFile(fileName);
 }

/*void MainWindow::zoom(int koef)
 {
    int hd, wd;
    int red,green,blue;
    QImage *Temp = new QImage(trunc(curImage->width() * koef/ 100),trunc(curImage->height() * koef / 100),QImage::Format_RGB32);
    double hdr, wdr, tmpw, tmph;
    double tw = (float) (Temp->width() - 1) / (curImage->width() - 1);
    double th = (float) (Temp->height() - 1) / (curImage->height() - 1);
    for (int i = 0; i < (Temp->height()); i++)
           {
           tmph = (float) i / th;
           for (int j = 0; j < (Temp->width()); j++)
               {
               hd = trunc(tmph);
               if (hd < 0) hd = 0;
                    else if (hd >= curImage->height() - 1) hd = curImage->height() - 2;
               hdr = tmph - hd;
               tmpw = (float)j / tw;
               wd = trunc(tmpw);
               if (wd < 0) wd = 0;
                  else if (wd >= curImage->width() - 1) wd = curImage->width() - 2;
               wdr = tmpw - wd;
               red = (1 - wdr) * (1 - hdr) *  qRed(curImage->pixel(wd,hd))
                     + wdr * (1 - hdr) * qRed(curImage->pixel(wd,hd + 1))
                     + wdr * hdr * qRed(curImage->pixel(wd + 1,hd + 1))
                     + (1 - wdr) * hdr * qRed(curImage->pixel(wd + 1,hd));
               green = (1 - wdr) * (1 - hdr) *  qGreen(curImage->pixel(wd,hd))
                     + wdr * (1 - hdr) * qGreen(curImage->pixel(wd,hd + 1))
                     + wdr * hdr * qGreen(curImage->pixel(wd + 1,hd + 1))
                     + (1 - wdr) * hdr * qGreen(curImage->pixel(wd + 1,hd));
               blue = (1 - wdr) * (1 - hdr) *  qBlue(curImage->pixel(wd,hd))
                     + wdr * (1 - hdr) * qBlue(curImage->pixel(wd,hd + 1))
                     + wdr * hdr * qBlue(curImage->pixel(wd + 1,hd + 1))
                     + (1 - wdr) * hdr * qBlue(curImage->pixel(wd + 1,hd));
               Temp->setPixel(j,i,qRgb(red,green,blue));
                }
           }
        isModified = true;
        *curImage = *Temp;
        image->convertFromImage(*curImage);
        delete Temp;
        spinBoxG2->setValue(100);
        statusBar()->showMessage(tr("Zoomed"), 2000);
        repaint();


 }*/

void MainWindow::rotation(int koef)
 {
    double k = koef - koefg;
    double rCos = cos(k * (asin(1) / 90)), rSin = sin(k * asin(1) / 90), xtemp, ytemp;
    int xneed, yneed, xtempi, ytempi;
    int red,green,blue;
    QImage *Temp = new QImage(curImage->width(),curImage->height(),QImage::Format_RGB32);
    double hdr, wdr;
    int crotx = (curImage->width() - 1) / 2, croty = (curImage->height() - 1) / 2;
    for (int i = 0; i < (Temp->width()); i++)
           {
           for (int j = 0; j < (Temp->height()); j++)
               {
                if ( (i == crotx)&&(j == croty) )
                    {
                    Temp->setPixel(i,j,curImage->pixel(i,j));
                    continue;
                    }
               xtemp = (i - crotx) * rCos - (croty - j) * rSin + crotx;
               ytemp = croty - (i - crotx) * rSin - (croty - j) * rCos;
               xtempi = (int) trunc(xtemp);
               xneed = xtempi;
               if (xtemp != xtempi) xneed++;
               ytempi = (int)trunc(ytemp);
               yneed = ytempi;
               if (ytemp != ytempi) yneed++;
               if (!((xtempi < 0) || (xneed >= curImage->width()) || (ytempi < 0) || (yneed >= curImage->height())))
               {
               hdr = xtemp - xtempi;
               wdr = ytemp - ytempi;
               red = (1 - wdr) * (1 - hdr) *  qRed(curImage->pixel(xtempi,ytempi))
                     + wdr * (1 - hdr) * qRed(curImage->pixel(xtempi,yneed))
                     + wdr * hdr * qRed(curImage->pixel(xneed,yneed))
                     + (1 - wdr) * hdr * qRed(curImage->pixel(xneed,ytempi));
               green = (1 - wdr) * (1 - hdr) *  qGreen(curImage->pixel(xtempi,ytempi))
                     + wdr * (1 - hdr) * qGreen(curImage->pixel(xtempi,yneed))
                     + wdr * hdr * qGreen(curImage->pixel(xneed,yneed))
                     + (1 - wdr) * hdr * qGreen(curImage->pixel(xneed ,ytempi));
               blue = (1 - wdr) * (1 - hdr) *  qBlue(curImage->pixel(xtempi,ytempi))
                     + wdr * (1 - hdr) * qBlue(curImage->pixel(xtempi,yneed))
                     + wdr * hdr * qBlue(curImage->pixel(xneed,yneed))
                     + (1 - wdr) * hdr * qBlue(curImage->pixel(xneed,ytempi));
               Temp->setPixel(i,j,qRgb(red,green,blue));}
                }
           }
        isModified = true;
        *curImage = *Temp;
        image->convertFromImage(*curImage);
        labelIm->setMinimumSize(curImage->width(), curImage->height());
        delete Temp;
        koefg = koef;
        statusBar()->showMessage(tr("Rotated"), 2000);
        repaint();


 }

void MainWindow::zoom(int koef)
 {
    double xtemp, ytemp;
    int xneed, yneed, xtempi, ytempi;
    int red,green,blue;
    QImage *Temp = new QImage(curImage->width(),curImage->height(),QImage::Format_RGB32);
    double hdr, wdr, k = (float)koef / koefp;
    int crotx = (curImage->width() - 1) / 2, croty = (curImage->height() - 1) / 2;
    for (int i = 0; i < (Temp->width()); i++)
           {
           for (int j = 0; j < (Temp->height()); j++)
               {
                if ( (i == crotx)&&(j == croty) )
                    {
                    Temp->setPixel(i,j,curImage->pixel(i,j));
                    continue;
                    }
               xtemp = ((i - crotx) / k) + crotx;
               ytemp = croty - ((croty - j) / k) ;
               xtempi = (int) trunc(xtemp);
               xneed = xtempi;
               if (xtemp != xtempi) xneed++;
               ytempi = (int)trunc(ytemp);
               yneed = ytempi;
               if (ytemp != ytempi) yneed++;
               if (!((xtempi < 0) || (xneed >= (curImage->width())) || (ytempi < 0) || (yneed >= (curImage->height()))))
               {
               hdr = xtemp - xtempi;
               wdr = ytemp - ytempi;
               red = (1 - wdr) * (1 - hdr) *  qRed(curImage->pixel(xtempi,ytempi))
                     + wdr * (1 - hdr) * qRed(curImage->pixel(xtempi,yneed))
                     + wdr * hdr * qRed(curImage->pixel(xneed,yneed))
                     + (1 - wdr) * hdr * qRed(curImage->pixel(xneed,ytempi));
               green = (1 - wdr) * (1 - hdr) *  qGreen(curImage->pixel(xtempi,ytempi))
                     + wdr * (1 - hdr) * qGreen(curImage->pixel(xtempi,yneed))
                     + wdr * hdr * qGreen(curImage->pixel(xneed,yneed))
                     + (1 - wdr) * hdr * qGreen(curImage->pixel(xneed ,ytempi));
               blue = (1 - wdr) * (1 - hdr) *  qBlue(curImage->pixel(xtempi,ytempi))
                     + wdr * (1 - hdr) * qBlue(curImage->pixel(xtempi,yneed))
                     + wdr * hdr * qBlue(curImage->pixel(xneed,yneed))
                     + (1 - wdr) * hdr * qBlue(curImage->pixel(xneed,ytempi));
               Temp->setPixel(i,j,qRgb(red,green,blue));}
                }
           }
        isModified = true;
        koefp = koef;
        *curImage = *Temp;
        image->convertFromImage(*curImage);
        labelIm->setMinimumSize(curImage->width(), curImage->height());
        delete Temp;
        statusBar()->showMessage(tr("Zoomed"), 2000);
        repaint();


 }


 void MainWindow::createActions()
 {

     openImAct = new QAction(tr("&Open..."), this);
     openImAct->setShortcuts(QKeySequence::Open);
     openImAct->setStatusTip(tr("Open an existing IMAGE"));
     connect(openImAct, SIGNAL(triggered()), this, SLOT(openIm()));

     saveImAct = new QAction(tr("&Save"), this);
     saveImAct->setShortcuts(QKeySequence::Save);
     saveImAct->setStatusTip(tr("Save the Image to disk"));
     connect(saveImAct, SIGNAL(triggered()), this, SLOT(saveIm()));

     saveImAsAct = new QAction(tr("Save &As..."), this);
     saveImAsAct->setShortcuts(QKeySequence::SaveAs);
     saveImAsAct->setStatusTip(tr("Save the Image under to disk a new name"));
     connect(saveImAsAct, SIGNAL(triggered()), this, SLOT(saveImAs()));

     exitAct = new QAction(tr("E&xit"), this);
     exitAct->setShortcuts(QKeySequence::Quit);
     exitAct->setStatusTip(tr("Exit poorPaint"));
     connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

     zoomAct = new QAction(tr("&Zoom"),this);
     zoomAct->setStatusTip(tr("Zoom"));
     connect(spinBoxG2, SIGNAL(valueChanged(int)), this, SLOT(zoom(int)));

     rotationAct = new QAction(tr("&Rotation"),this);
     rotationAct->setStatusTip(tr("Rotation"));
     connect(spinBoxG1, SIGNAL(valueChanged(int)), this, SLOT(rotation(int)));

 }

 void MainWindow::createMenus()
 {
     fileMenu = menuBar()->addMenu(tr("&File"));
     fileMenu->addAction(openImAct);
     fileMenu->addAction(saveImAct);
     fileMenu->addAction(saveImAsAct);
     fileMenu->addSeparator();
     fileMenu->addAction(exitAct);

     /*editMenu = menuBar()->addMenu(tr("&Edit"));
     editMenu->addAction(cutAct);
     editMenu->addAction(copyAct);
     editMenu->addAction(pasteAct);*/

     menuBar()->addSeparator();
 }



 void MainWindow::createStatusBar()
 {
     statusBar()->showMessage(tr("Ready"));
 }

 QString MainWindow::strippedName(const QString &fullFileName)
 {
     return QFileInfo(fullFileName).fileName();
 }
