/*************************************************************************
 * Copyright (c) 2011 AT&T Intellectual Property
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
 *
 * Contributors: Details at https://graphviz.org
 *************************************************************************/

#include "config.h"

#include "imageviewer.h"
#include "mdichild.h"
#include <QtGlobal>

ImageViewer::ImageViewer()
{
    imageLabel = new QLabel;
    imageLabel->setBackgroundRole(QPalette::Base);
    imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    imageLabel->setScaledContents(true);

    scrollArea = new QScrollArea;
    scrollArea->setBackgroundRole(QPalette::Dark);
    scrollArea->setWidget(imageLabel);
    setCentralWidget(scrollArea);

    createActions();
    createMenus();

    setWindowTitle(tr(""));
    resize(800, 600);

    setWindowIcon(QIcon(QStringLiteral(":/images/icon.png")));
}

bool ImageViewer::open(const QString &fileName)
{
    if (!fileName.isEmpty()) {
	QImage image(fileName);
	if (image.isNull()) {
	    return false;
	}
	imageLabel->setPixmap(QPixmap::fromImage(image));
	scaleFactor = 1.0;
	fitToWindowAct->setEnabled(true);
	updateActions();

	if (!fitToWindowAct->isChecked())
	    imageLabel->adjustSize();
    }
    return true;
}

void ImageViewer::print()
{
#ifndef QT_NO_PRINTER
    auto get_pixmap = [&]() {
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
        Q_ASSERT(imageLabel->pixmap());
        return *imageLabel->pixmap();
#else
        return imageLabel->pixmap(Qt::ReturnByValue);
#endif
    };
    QPrintDialog dialog(&printer, this);
    if (dialog.exec()) {
	QPainter painter(&printer);
	QRect rect = painter.viewport();
	QSize size = get_pixmap().size();
	size.scale(rect.size(), Qt::KeepAspectRatio);
	painter.setViewport(rect.x(), rect.y(), size.width(),
			    size.height());
	painter.setWindow(get_pixmap().rect());
	painter.drawPixmap(0, 0, get_pixmap());
    }
#endif
}

void ImageViewer::zoomIn()
{
    scaleImage(1.25);
}

void ImageViewer::zoomOut()
{
    scaleImage(0.8);
}

void ImageViewer::normalSize()
{
    imageLabel->adjustSize();
    scaleFactor = 1.0;
}

void ImageViewer::fitToWindow()
{
    bool fitToWindow = fitToWindowAct->isChecked();
    scrollArea->setWidgetResizable(fitToWindow);
    if (!fitToWindow) {
	normalSize();
    }
    updateActions();
}

void ImageViewer::about()
{
    QMessageBox::about(this, tr("About Image Viewer"),
		       tr
		       ("<p>The <b>Image Viewer</b> example shows how to combine QLabel "
			"and QScrollArea to display an image. QLabel is typically used "
			"for displaying a text, but it can also display an image. "
			"QScrollArea provides a scrolling view around another widget. "
			"If the child widget exceeds the size of the frame, QScrollArea "
			"automatically provides scroll bars. </p><p>The example "
			"demonstrates how QLabel's ability to scale its contents "
			"(QLabel::scaledContents), and QScrollArea's ability to "
			"automatically resize its contents "
			"(QScrollArea::widgetResizable), can be used to implement "
			"zooming and scaling features. </p><p>In addition the example "
			"shows how to use QPainter to print an image.</p>"));
}

void ImageViewer::createActions()
{
    printAct = new QAction(tr("&Print..."), this);
    printAct->setShortcut(tr("Ctrl+P"));
    printAct->setEnabled(false);
    connect(printAct, &QAction::triggered, this, &ImageViewer::print);

    exitAct = new QAction(tr("E&xit"), this);
    exitAct->setShortcut(tr("Ctrl+Q"));
    connect(exitAct, &QAction::triggered, this, &ImageViewer::close);

    zoomInAct = new QAction(tr("Zoom &In (25%)"), this);
    zoomInAct->setShortcut(tr("Ctrl++"));
    zoomInAct->setEnabled(false);
    connect(zoomInAct, &QAction::triggered, this, &ImageViewer::zoomIn);

    zoomOutAct = new QAction(tr("Zoom &Out (25%)"), this);
    zoomOutAct->setShortcut(tr("Ctrl+-"));
    zoomOutAct->setEnabled(false);
    connect(zoomOutAct, &QAction::triggered, this, &ImageViewer::zoomOut);

    normalSizeAct = new QAction(tr("&Normal Size"), this);
    normalSizeAct->setShortcut(tr("Ctrl+S"));
    normalSizeAct->setEnabled(false);
    connect(normalSizeAct, &QAction::triggered, this, &ImageViewer::normalSize);

    fitToWindowAct = new QAction(tr("&Fit to Window"), this);
    fitToWindowAct->setEnabled(false);
    fitToWindowAct->setCheckable(true);
    fitToWindowAct->setShortcut(tr("Ctrl+F"));
    connect(fitToWindowAct, &QAction::triggered, this,
            &ImageViewer::fitToWindow);

    aboutAct = new QAction(tr("&About"), this);
    connect(aboutAct, &QAction::triggered, this, &ImageViewer::about);

    aboutQtAct = new QAction(tr("About &Qt"), this);
    connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt);
}

void ImageViewer::createMenus()
{

    viewMenu = new QMenu(tr("&View"), this);
    viewMenu->addAction(zoomInAct);
    viewMenu->addAction(zoomOutAct);
    viewMenu->addAction(normalSizeAct);
    viewMenu->addSeparator();
    viewMenu->addAction(fitToWindowAct);

    menuBar()->addMenu(viewMenu);
}

void ImageViewer::updateActions()
{
    zoomInAct->setEnabled(!fitToWindowAct->isChecked());
    zoomOutAct->setEnabled(!fitToWindowAct->isChecked());
    normalSizeAct->setEnabled(!fitToWindowAct->isChecked());
}

void ImageViewer::scaleImage(double factor)
{
    auto get_pixmap = [&]() {
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
        Q_ASSERT(imageLabel->pixmap());
        return *imageLabel->pixmap();
#else
        return imageLabel->pixmap(Qt::ReturnByValue);
#endif
    };
    scaleFactor *= factor;
    imageLabel->resize(scaleFactor * get_pixmap().size());

    adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
    adjustScrollBar(scrollArea->verticalScrollBar(), factor);

    zoomInAct->setEnabled(scaleFactor < 3.0);
    zoomOutAct->setEnabled(scaleFactor > 0.333);
}

void ImageViewer::adjustScrollBar(QScrollBar * scrollBar, double factor)
{
    scrollBar->setValue(int (factor * scrollBar->value()
			     +
			     ((factor - 1) * scrollBar->pageStep() / 2)));
}

void ImageViewer::closeEvent(QCloseEvent * event)
{
    this->graphWindow->previewFrm = nullptr;
    event->accept();

}
