/** @file imageview.cpp
 * SOubor s tridou tridy ImageView dedici ze tridy QWidget
 * pro zobrazeni noveho okna s fotografii v puvodni velikosti
 */

#include "imageview.h"
#include "imagewidgetslist.h"
#include <QCloseEvent>
#include <QDebug>
#include <QKeyEvent>
#include <QScroller>
#include <QShowEvent>

QSize ImageView::rememberedWindowSize;
bool ImageView::hasRememberedWindowSize = false;

ImageView::ImageView(QWidget* parent)
    : QWidget(parent)
    , img(nullptr)
{
    setFocusPolicy(Qt::StrongFocus);
    imageL = new QLabel;
    scrollArea = new ScrollArea;
    this->setLayout(new QHBoxLayout);
    connect(scrollArea, SIGNAL(changeSize(int)), this, SLOT(changeImageSize(int)));
    QScroller::grabGesture(scrollArea, QScroller::LeftMouseButtonGesture);

    this->layout()->setContentsMargins(0, 0, 0, 0);
    this->layout()->addWidget(scrollArea);
    this->setWindowModality(Qt::ApplicationModal);
    this->adjustSize();
}

ImageView::~ImageView()
{
    delete img;
}

QSize ImageView::sizeHint() const
{
    return QSize(1024, 768);
}

void ImageView::setNavigation(ImageWidgetsList* list, int index)
{
    imageList = list;
    currentIndex = index;
}

void ImageView::showAdjacentImage(int delta)
{
    if (!imageList || imageList->isEmpty()) {
        return;
    }
    const int newIndex = imageList->selectRelative(delta, currentIndex);
    if (newIndex < 0) {
        return;
    }
    currentIndex = newIndex;
    setImage(imageList->at(currentIndex)->imageData->pictureName);
}

void ImageView::showAdjacentRow(int rowDelta)
{
    if (!imageList || imageList->isEmpty()) {
        return;
    }
    const int newIndex = imageList->selectRelativeRow(rowDelta, currentIndex);
    if (newIndex < 0) {
        return;
    }
    currentIndex = newIndex;
    setImage(imageList->at(currentIndex)->imageData->pictureName);
}

void ImageView::showEvent(QShowEvent* event)
{
    QWidget::showEvent(event);
    setFocus();
}

void ImageView::setImage(QString pictureName)
{
    if (img) {
        delete img;
        img = nullptr;
    }

    this->setWindowTitle(pictureName);
    img = new QImage(pictureName);
    if (img->isNull()) {
        // img je null
        return;
    }
    std::unique_ptr<Exiv2::Image> image;

    bool isExif = false;
    try {
        image = Exiv2::ImageFactory::open(std::string(pictureName.toUtf8()));
        isExif = true;
    } catch (Exiv2::Error& e) {
        qDebug() << "Caught Exiv2 exception 2 '" << e.what() << "'";
        isExif = false;
    }

    if (isExif) {
        image.get();
        image->readMetadata();
        QTransform rot;
        Exiv2::ExifData& exifData = image->exifData();
        if (!exifData.empty()) {
            Exiv2::ExifKey key("Exif.Image.Orientation");
            Exiv2::ExifData::iterator pos = exifData.findKey(key);
            if (pos != exifData.end()) {
                // qDebug() << exifData["Exif.Image.Orientation"].toString().data() << "iiii";
                QString str = exifData["Exif.Image.Orientation"].toString().data();
                switch (str.toInt()) {
                case 3: // obraz otoceny o 180stupnu
                    *img = img->transformed(rot.rotate(180));
                    break;
                case 6: // obraz otoceny o 90stupnu
                    *img = img->transformed(rot.rotate(90));
                    break;
                case 8: // obraz otoceny o 280stupnu
                    *img = img->transformed(rot.rotate(280));
                    break;
                default:
                    break;
                }
            }
        }
    }
    this->setContentsMargins(QMargins(0, 0, 0, 0));
    scrollArea->setContentsMargins(QMargins(0, 0, 0, 0));

    currentSize = QSize(this->size().width() - 2, this->size().height() - 2);

    imageL->setPixmap(QPixmap::fromImage((img->scaled(currentSize, Qt::KeepAspectRatio))));

    scrollArea->setWidget(imageL);
    scrollArea->resize(this->size());
    if (hasRememberedWindowSize) {
        resize(rememberedWindowSize);
    } else {
        resize(scrollArea->widget()->width() + 2, scrollArea->widget()->height() + 2);
    }
    imageL->setAlignment(Qt::AlignCenter);
}

void ImageView::closeEvent(QCloseEvent* event)
{
    const QSize windowSize = size();
    if (windowSize.isValid() && !windowSize.isEmpty()) {
        rememberedWindowSize = windowSize;
        hasRememberedWindowSize = true;
    }
    QWidget::closeEvent(event);
}

void ImageView::resizeEvent(QResizeEvent* event)
{
    event->accept();
    if (!img || img->isNull()) {
        return;
    }
    currentSize = QSize(this->size().width() - 2, this->size().height() - 2);
    imageL->setPixmap(QPixmap::fromImage((img->scaled(currentSize, Qt::KeepAspectRatio))));

    scrollArea->resize(this->size());

    // scrollArea->checkScrollBars();
}

void ImageView::wheelEvent(QWheelEvent* event)
{
    if (event->modifiers() & Qt::ControlModifier) {
        QSize s;
        if (event->angleDelta().y() < 0) {
            qDebug() << imageL->width() << imageL->height();
            if (imageL->width() > 30 && imageL->height() > 30) {
                s = QSize(imageL->width() * 0.90, imageL->height() * 0.90);
            } else {
                return;
            }

        } else {
            s = QSize(imageL->width() * 1.1, imageL->height() * 1.1);
        }
        qDebug() << s;
        imageL->setPixmap(QPixmap::fromImage((img->scaled(s, Qt::KeepAspectRatio))));
        imageL->resize(s);
        event->accept();
    }
}

void ImageView::changeImageSize(int delta)
{
    if (delta < 0) {
        if (currentSize.width() > 60 && currentSize.height() > 60) {
            currentSize = QSize(currentSize.width() * 0.90, currentSize.height() * 0.90);
        } else {
            return;
        }
    } else {
        currentSize = QSize(currentSize.width() * 1.1, currentSize.height() * 1.1);
    }

    imageL->setPixmap(QPixmap::fromImage((img->scaled(currentSize, Qt::KeepAspectRatio))));
    scrollArea->setWidget(imageL);
}

void ImageView::keyPressEvent(QKeyEvent* ev)
{
    switch (ev->key()) {
    case Qt::Key_Escape:
        close();
        ev->accept();
        return;
    case Qt::Key_Left:
        showAdjacentImage(-1);
        ev->accept();
        return;
    case Qt::Key_Right:
        showAdjacentImage(1);
        ev->accept();
        return;
    case Qt::Key_Up:
        showAdjacentRow(-1);
        ev->accept();
        return;
    case Qt::Key_Down:
        showAdjacentRow(1);
        ev->accept();
        return;
    default:
        QWidget::keyPressEvent(ev);
    }
}
