//SPDX-License-Identifier: GPL-3.0-or-later
/*****************************************************************************/
/*  Copyright 2021 Avalanche Warning Service Tyrol                LWD-TIROL  */
/*****************************************************************************/
/* This file is part of INIshell.
   INIshell is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   INIshell is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with INIshell.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <src/panels/ImageView.h>
#include <src/main/colors.h>
#include <src/main/inishell.h>

#include <QDesktopServices>
#include <QHBoxLayout>
#include <QImage>
#include <QImageReader>
#include <QPixmap>
#include <QScrollArea>
#include <QVBoxLayout>

#ifdef DEBUG
	#include <iostream>
#endif //def DEBUG

/**
 * @class ImageView
 * @brief Default constructor for an ImageView.
 * @details An ImageView is used to display an image.
 * @param[in] section unused
 * @param[in] key unused
 * @param[in] options XML node responsible for this panel with all options and children.
 * @param[in] no_spacers Keep a tight layout for this panel.
 * @param[in] parent The parent widget.
 */
ImageView::ImageView(const QString &section, const QString &key, const QDomNode &options, const bool &no_spacers,
	QWidget *parent) : Atomic(section, key, parent)
{
	this->setUpdatesEnabled(false);
	this->setProperty("no_ini", true); //display panel, does not contribute to INI

	/* image and caption labels */
	const bool use_border = options.toElement().attribute("border").toLower() != "false";
	image_label_ = new QLabel(this);
	if (use_border) //draw rectangle around image (default: true)?
		image_label_->setStyleSheet("QLabel {background-color: " + colors::getQColor("app_bg").name() +
			"; border: 1px solid " + colors::getQColor("normal").name() + "}");
	else
		image_label_->setStyleSheet("QLabel {background-color: " + colors::getQColor("app_bg").name() + "}");

	caption_label_ = new QLabel(this);
	caption_label_->setStyleSheet("QLabel {font: italic; color: " + colors::getQColor("info").name() + "}");

	/* scroll area and label layout */
	auto *label_layout( new QVBoxLayout );

	const bool enable_scrolling = options.toElement().attribute("scroll").toLower() != "false";
	Qt::AlignmentFlag img_alignment = Qt::AlignLeft;
	if (options.toElement().attribute("align").toLower() == "center")
		img_alignment = Qt::AlignCenter;
	else if (options.toElement().attribute("align").toLower() == "right")
		img_alignment = Qt::AlignRight;

	if (enable_scrolling) { //give image a separate scroll bar (in addition to the main contents, default: true)?
		auto scroll_area = new QScrollArea(this);
		scroll_area->setWidgetResizable(true);
		scroll_area->setWidget(image_label_);
		label_layout->addWidget(scroll_area, 0, img_alignment);
	} else { //do not use/create a scroll bar
		label_layout->addWidget(image_label_, 0, img_alignment);

	}
	label_layout->addWidget(caption_label_);

	/* main layout */
	auto *main_layout( new QHBoxLayout );
	main_layout->addLayout(label_layout);

	setLayoutMargins(main_layout);
	addHelp(main_layout, options, no_spacers);
	this->setLayout(main_layout);
	setOptions(options);
	this->setUpdatesEnabled(true);
}

/**
 * @brief Event listener for mouse clicks.
 * @param[in] event The mouse event.
 */
void ImageView::mouseReleaseEvent(QMouseEvent *event)
{
	if (!url_.isEmpty())
		QDesktopServices::openUrl(url_);
	event->accept();
}

/**
 * @brief Parse options for an ImageView from XML.
 * @param[in] options XML node holding the ImageView.
 */
void ImageView::setOptions(const QDomNode &options)
{
	QString path( options.toElement().attribute("path") );
	if (QFileInfo( path ).isRelative())
		path = QFileInfo( getMainWindow()->getCurrentApplicationPath() ).absolutePath() + "/" + path;
	const QString caption( options.toElement().attribute("caption") );

	const bool success = loadImage(path);
	if (success) {
		caption_label_->setText(caption);
	} else {
		image_label_->setText(options.toElement().attribute("alt")); //display alt text
		caption_label_->setText(tr(R"(Could not read image "%1".)").arg(path));
	}
	url_ = options.toElement().attribute("url"); //clicks on the image lead to this url
	if (!url_.isEmpty())
		image_label_->setCursor(QCursor(Qt::CursorShape::PointingHandCursor));
}

/**
 * @brief Load an image to display.
 * @param[in] path Path of image to read. If the path is relative, the XML's parent
 * path will be prepended.
 * @return True if image read-in was successful.
 */
bool ImageView::loadImage(const QString &path)
{
	QImageReader imgview( path );
	const QImage img( imgview.read() );
	if (img.isNull())
		return false;
	image_label_->setPixmap(QPixmap::fromImage(img));
	return true;
}
