//SPDX-License-Identifier: GPL-3.0-or-later
/*****************************************************************************/
/*  Copyright 2019 WSL Institute for Snow and Avalanche Research  SLF-DAVOS  */
/*****************************************************************************/
/* 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/gui/MainPanel.h>
#include <src/gui/SectionButton.h>
#include <src/gui/WorkflowPanel.h>
#include <src/main/colors.h>
#include <src/main/constants.h>
#include <src/main/inishell.h>
#include <src/main/os.h>
#include <src/main/settings.h>
#include <src/main/XMLReader.h>
#include <src/panels/dynamic_panels.h>
#include <src/panels/panels.h>

#include <QGroupBox>
#include <QHBoxLayout>
#include <QListWidget>
#include <QPushButton>
#include <QRegularExpression>
#include <QSplitter>
#include <QVBoxLayout>

#ifdef DEBUG
	#include <iostream>
#endif

/**
 * @class MainPanel
 * @brief Constructor for the main panel, i. e. the tab widget with scroll area children.
 * @param[in] parent The parent widget (the main window).
 */
MainPanel::MainPanel(QWidget *parent) : QWidget(parent)
{
	/* widget(s) on the left side and main tab bar */
	workflow_panel_ = new WorkflowPanel;
	workflow_stack_ = new QStackedWidget;
	section_tab_ = new SectionTab;
	workflow_stack_->addWidget(section_tab_);

	/* main layout */
	auto *main_layout( new QHBoxLayout );
	splitter_ = new QSplitter;
	splitter_->addWidget(workflow_panel_); //allow to resize with mouse
	splitter_->addWidget(workflow_stack_);
	setSplitterSizes();
	main_layout->addWidget(splitter_);
	this->setLayout(main_layout);

	displayInfo(); //startup info text
}

/**
 * @brief Display some info and the SLF logo on program start.
 */
void MainPanel::displayInfo()
{
	static const QString message(tr("<br> \
	    &nbsp;&nbsp;Welcome to <b>INIshell</b>, a dynamic graphical user interface builder to manage INI files.<br> \
	    &nbsp;&nbsp;Double-click an application to the left to begin.<br><br> \
		&nbsp;&nbsp;For help, click \"Help\" in the menu and visit <a href=\"https://gitlabext.wsl.ch/snow-models/inishell\">INIshell's project page</a>.<br> \
		&nbsp;&nbsp;There, you will also find the well-documented <a href=\"https://gitlabext.wsl.ch/snow-models/inishell/-/tree/master\">source code</a>.<br> \
	    &nbsp;&nbsp;If you don't know where to begin, press %1. \
	").arg(os::getHelpSequence()));

	auto *info_scroll( new QScrollArea );
	info_scroll->setWidgetResizable(true);

	/* SLF logo */
	QLabel *info_label( new QLabel );
	info_label->setAlignment(Qt::AlignBottom | Qt::AlignRight);
	info_label->setStyleSheet("QLabel {background-color: " + colors::getQColor("app_bg").name() + "}");
	const QPixmap logo(":/icons/slf_desaturated.svg");
	info_label->setPixmap(logo);

	/* info text */
	QLabel *info_text( new QLabel(info_label) );
	info_text->setTextFormat(Qt::RichText);
	info_text->setTextInteractionFlags(Qt::TextBrowserInteraction);
	info_text->setOpenExternalLinks(true);
	info_text->setText(message);
	info_scroll->setWidget(info_label);

	section_tab_->addTab(info_scroll, "Info");
}

/**
 * @brief Query the splitter's current sizes.
 * @return Current sizes of the splitter's panels.
 */
QList<int> MainPanel::getSplitterSizes() const
{
	return splitter_->sizes();
}

/**
 * @brief Set sizes of the panels the splitter manages.
 * @param[in] sizes The sizes the splitter should give to its panels.
 * @param[in] enforce_visible Show the workflow with default size if its size is saved
 * to be zero?
 */
void MainPanel::setSplitterSizes(QList<int> sizes, bool enforce_visible)
{
	splitter_->setStretchFactor(0, Cst::proportion_workflow_horizontal_percent);
	splitter_->setStretchFactor(1, 100 - Cst::proportion_workflow_horizontal_percent);
	if (!sizes.isEmpty()) {
		splitter_->setSizes(sizes);
		return;
	}
	bool workflow_success, main_success;
	const int width_workflow = getSetting("auto::sizes::splitter_workflow", "size").toInt(&workflow_success);
	const int width_mainpanel = getSetting("auto::sizes::splitter_mainpanel", "size").toInt(&main_success);
	if (workflow_success && main_success && workflow_success && !(enforce_visible && width_workflow < 20) )
		splitter_->setSizes(sizes << width_workflow << width_mainpanel);
	else //reset to default
		splitter_->setSizes(QList<int>( {Cst::width_inishell_default * Cst::proportion_workflow_horizontal_percent / 100,
			Cst::width_inishell_default * (100 - Cst::proportion_workflow_horizontal_percent) / 100} )); //has constraints anyway - set something big
}

/**
 * @brief Remove all GUI elements.
 * @details This function clears the main GUI itself, i. e. all panels read from XML, including
 * the workflow panels.
 */
void MainPanel::clearGuiElements()
{
	section_tab_->clear();
	workflow_panel_->clearXmlPanels();
}

/**
 * @brief Reset the whole GUI to default values.
 */
void MainPanel::clearGui(const bool &set_default)
{
	clearDynamicPanels<Replicator>(); //clear special panels (the ones that can produce INI keys)
	clearDynamicPanels<Selector>(); //cf. notes there
	const QList<Atomic *> panel_list( section_tab_->findChildren<Atomic *>() ); //clear all others
	for (auto &panel : panel_list)
		panel->clear(set_default);
}
