// qpwgraph_options.cpp
//
/****************************************************************************
   Copyright (C) 2021-2025, rncbc aka Rui Nuno Capela. All rights reserved.

   This program 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 2
   of the License, or (at your option) any later version.

   This program 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 this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

*****************************************************************************/

#include "config.h"

#include "qpwgraph_options.h"

#include "qpwgraph_main.h"
#include "qpwgraph_config.h"

#include <QMessageBox>
#include <QPushButton>

#include <QLineEdit>

#ifdef CONFIG_SYSTEM_TRAY
#include <QSystemTrayIcon>
#endif


//----------------------------------------------------------------------------
// qpwgraph_options -- UI wrapper form.

// Constructor.
qpwgraph_options::qpwgraph_options ( qpwgraph_main *parent )
	: QDialog(parent)
{
	// Setup UI struct...
	m_ui.setupUi(this);

	// Initialize dirty control state.
	m_dirty = 0;

	m_dirty_filter = 0;
	m_dirty_merger = 0;

	// Setup current options...
	qpwgraph_config *config = parent->config();
	if (config) {
		config->loadComboBoxHistory(m_ui.MergerNodesNameComboBox);
		config->loadComboBoxHistory(m_ui.FilterNodesNameComboBox);
	#ifdef CONFIG_SYSTEM_TRAY
		m_ui.SystemTrayEnabledCheckBox->setChecked(
			config->isSystemTrayEnabled());
		m_ui.SystemTrayQueryCloseCheckBox->setChecked(
			config->isSystemTrayQueryClose());
		m_ui.SystemTrayStartMinimizedCheckBox->setChecked(
			config->isStartMinimized());
	#endif
		m_ui.PatchbayQueryQuitCheckBox->setChecked(
			config->isPatchbayQueryQuit());
	#ifdef CONFIG_ALSA_MIDI
		m_ui.AlsaMidiEnabledCheckBox->setChecked(
			config->isAlsaMidiEnabled());
	#endif
	}

#ifdef CONFIG_SYSTEM_TRAY
	if (!QSystemTrayIcon::isSystemTrayAvailable()) {
		m_ui.SystemTrayEnabledCheckBox->setEnabled(false);
		m_ui.SystemTrayQueryCloseCheckBox->setEnabled(false);
		m_ui.SystemTrayStartMinimizedCheckBox->setChecked(false);
	}
#else
	m_ui.SystemTrayEnabledCheckBox->hide();
	m_ui.SystemTrayQueryCloseCheckBox->hide();
	m_ui.SystemTrayStartMinimizedCheckBox->hide();
#endif

#ifndef CONFIG_ALSA_MIDI
	m_ui.AlsaMidiEnabledCheckBox->hide();
#endif

	// Filter/hide list management...
	//
	if (config) {
		m_ui.FilterNodesEnabledCheckBox->setChecked(
			config->isFilterNodesEnabled());
		m_ui.FilterNodesNameComboBox->lineEdit()->setClearButtonEnabled(true);
		m_ui.FilterNodesNameComboBox->lineEdit()->setPlaceholderText(
			m_ui.FilterNodesNameComboBox->toolTip());
		m_ui.FilterNodesNameComboBox->setCurrentText(QString());
		m_ui.FilterNodesListWidget->clear();
		m_ui.FilterNodesListWidget->addItems(
			config->filterNodesList());
	}

	// Merger/unify list management...
	//
	if (config) {
		m_ui.MergerNodesEnabledCheckBox->setChecked(
			config->isMergerNodesEnabled());
		m_ui.MergerNodesNameComboBox->lineEdit()->setClearButtonEnabled(true);
		m_ui.MergerNodesNameComboBox->lineEdit()->setPlaceholderText(
			m_ui.MergerNodesNameComboBox->toolTip());
		m_ui.MergerNodesNameComboBox->setCurrentText(QString());
		m_ui.MergerNodesListWidget->clear();
		m_ui.MergerNodesListWidget->addItems(
			config->mergerNodesList());
	}

	// Try to restore old window positioning.
	adjustSize();

	// UI connections...
#ifdef CONFIG_SYSTEM_TRAY
	QObject::connect(m_ui.SystemTrayEnabledCheckBox,
		SIGNAL(stateChanged(int)),
		SLOT(changed()));
	QObject::connect(m_ui.SystemTrayQueryCloseCheckBox,
		SIGNAL(stateChanged(int)),
		SLOT(changed()));
	QObject::connect(m_ui.SystemTrayStartMinimizedCheckBox,
		SIGNAL(stateChanged(int)),
		SLOT(changed()));
#endif
	QObject::connect(m_ui.PatchbayQueryQuitCheckBox,
		SIGNAL(stateChanged(int)),
		SLOT(changed()));
#ifdef CONFIG_ALSA_MIDI
	QObject::connect(m_ui.AlsaMidiEnabledCheckBox,
		SIGNAL(stateChanged(int)),
		SLOT(changed()));
#endif

	QObject::connect(m_ui.FilterNodesEnabledCheckBox,
		SIGNAL(stateChanged(int)),
		SLOT(changedFilterNodes()));
	QObject::connect(m_ui.FilterNodesNameComboBox,
		SIGNAL(editTextChanged(const QString&)),
		SLOT(stabilize()));
	QObject::connect(m_ui.FilterNodesAddToolButton,
		SIGNAL(clicked()),
		SLOT(addFilterNodes()));
	QObject::connect(m_ui.FilterNodesListWidget,
		SIGNAL(itemSelectionChanged()),
		SLOT(selectFilterNodes()));
	QObject::connect(m_ui.FilterNodesRemoveToolButton,
		SIGNAL(clicked()),
		SLOT(removeFilterNodes()));
	QObject::connect(m_ui.FilterNodesClearToolButton,
		SIGNAL(clicked()),
		SLOT(clearFilterNodes()));

	QObject::connect(m_ui.MergerNodesEnabledCheckBox,
		SIGNAL(stateChanged(int)),
		SLOT(changedMergerNodes()));
	QObject::connect(m_ui.MergerNodesNameComboBox,
		SIGNAL(editTextChanged(const QString&)),
		SLOT(stabilize()));
	QObject::connect(m_ui.MergerNodesAddToolButton,
		SIGNAL(clicked()),
		SLOT(addMergerNodes()));
	QObject::connect(m_ui.MergerNodesListWidget,
		SIGNAL(itemSelectionChanged()),
		SLOT(selectMergerNodes()));
	QObject::connect(m_ui.MergerNodesRemoveToolButton,
		SIGNAL(clicked()),
		SLOT(removeMergerNodes()));
	QObject::connect(m_ui.MergerNodesClearToolButton,
		SIGNAL(clicked()),
		SLOT(clearMergerNodes()));

	QObject::connect(m_ui.DialogButtonBox,
		SIGNAL(accepted()),
		SLOT(accept()));
	QObject::connect(m_ui.DialogButtonBox,
		SIGNAL(rejected()),
		SLOT(reject()));

	// Ready?
	stabilize();
}


// Destructor.
qpwgraph_options::~qpwgraph_options (void)
{
}


// Reject options (Cancel button slot).
void qpwgraph_options::reject (void)
{
	bool ret = true;

	// Check if there's any pending changes...
	if (m_dirty > 0) {
		switch (QMessageBox::warning(this,
			tr("Warning"),
			tr("Some options have been changed.") + "\n\n" +
			tr("Do you want to apply the changes?"),
			QMessageBox::Apply | QMessageBox::Discard | QMessageBox::Cancel)) {
		case QMessageBox::Apply:
			accept();
			return;
		case QMessageBox::Discard:
			break;
		default: // Cancel.
			ret = false;
		}
	}

	if (ret)
		QDialog::reject();
}


// Accept options (OK button slot).
void qpwgraph_options::accept (void)
{
	qpwgraph_config *config = nullptr;
	qpwgraph_main *parent = qobject_cast<qpwgraph_main *> (parentWidget());
	if (parent)
		config = parent->config();
	if (config) {
	#ifdef CONFIG_SYSTEM_TRAY
		config->setSystemTrayEnabled(
			m_ui.SystemTrayEnabledCheckBox->isChecked());
		config->setSystemTrayQueryClose(
			m_ui.SystemTrayQueryCloseCheckBox->isChecked());
		config->setStartMinimized(
			m_ui.SystemTrayStartMinimizedCheckBox->isChecked());
	#endif
		config->setPatchbayQueryQuit(
			m_ui.PatchbayQueryQuitCheckBox->isChecked());
	#ifdef CONFIG_ALSA_MIDI
		config->setAlsaMidiEnabled(
			m_ui.AlsaMidiEnabledCheckBox->isChecked());
	#endif
		if (m_dirty_filter > 0) {
			config->setFilterNodesEnabled(
				m_ui.FilterNodesEnabledCheckBox->isChecked());
			QStringList nodes;
			const int n = m_ui.FilterNodesListWidget->count();
			for (int i = 0; i < n; ++i) {
				QListWidgetItem *item = m_ui.FilterNodesListWidget->item(i);
				if (item)
					nodes.append(item->text());
			}
			config->setFilterNodesList(nodes);
			config->setFilterNodesDirty(true);
			m_dirty_filter = 0;
		}
		config->saveComboBoxHistory(m_ui.FilterNodesNameComboBox);
		if (m_dirty_merger > 0) {
			config->setMergerNodesEnabled(
				m_ui.MergerNodesEnabledCheckBox->isChecked());
			QStringList nodes;
			const int n = m_ui.MergerNodesListWidget->count();
			for (int i = 0; i < n; ++i) {
				QListWidgetItem *item = m_ui.MergerNodesListWidget->item(i);
				if (item)
					nodes.append(item->text());
			}
			config->setMergerNodesList(nodes);
			config->setMergerNodesDirty(true);
			m_dirty_merger = 0;
		}
		config->saveComboBoxHistory(m_ui.MergerNodesNameComboBox);
		parent->updateOptions();
	}

	QDialog::accept();
}


// Dirty up options.
void qpwgraph_options::changed (void)
{
	++m_dirty;

	stabilize();
}


// Filter/hide list management...
//
void qpwgraph_options::changedFilterNodes (void)
{
	++m_dirty_filter;

	changed();
}


void qpwgraph_options::selectFilterNodes (void)
{
	QListWidgetItem *item = m_ui.FilterNodesListWidget->currentItem();
	if (item)
		m_ui.FilterNodesNameComboBox->setEditText(item->text());

	stabilize();
}


void qpwgraph_options::addFilterNodes (void)
{
	const QString& node_name
		= m_ui.FilterNodesNameComboBox->currentText();
	if (node_name.isEmpty())
		return;

	m_ui.FilterNodesListWidget->addItem(node_name);
	m_ui.FilterNodesListWidget->setCurrentRow(
		m_ui.FilterNodesListWidget->count() - 1);

	const int i = m_ui.FilterNodesNameComboBox->findText(node_name);
	if (i >= 0)
		m_ui.FilterNodesNameComboBox->removeItem(i);
	m_ui.FilterNodesNameComboBox->insertItem(0, node_name);
	m_ui.FilterNodesNameComboBox->setEditText(QString());

	m_ui.FilterNodesListWidget->setFocus();

	changedFilterNodes();
}


void qpwgraph_options::removeFilterNodes (void)
{
	const int i	= m_ui.FilterNodesListWidget->currentRow();
	if (i < 0)
		return;

	QListWidgetItem *item = m_ui.FilterNodesListWidget->takeItem(i);
	if (item)
		delete item;

	changedFilterNodes();
}


void qpwgraph_options::clearFilterNodes (void)
{
	m_ui.FilterNodesListWidget->clear();

	changedFilterNodes();
}


// Merger/unify list management...
//
void qpwgraph_options::changedMergerNodes (void)
{
	++m_dirty_merger;

	changed();
}


void qpwgraph_options::selectMergerNodes (void)
{
	QListWidgetItem *item = m_ui.MergerNodesListWidget->currentItem();
	if (item)
		m_ui.MergerNodesNameComboBox->setEditText(item->text());

	stabilize();
}


void qpwgraph_options::addMergerNodes (void)
{
	const QString& node_name
		= m_ui.MergerNodesNameComboBox->currentText();
	if (node_name.isEmpty())
		return;

	m_ui.MergerNodesListWidget->addItem(node_name);
	m_ui.MergerNodesListWidget->setCurrentRow(
		m_ui.MergerNodesListWidget->count() - 1);

	const int i = m_ui.MergerNodesNameComboBox->findText(node_name);
	if (i >= 0)
		m_ui.MergerNodesNameComboBox->removeItem(i);
	m_ui.MergerNodesNameComboBox->insertItem(0, node_name);
	m_ui.MergerNodesNameComboBox->setEditText(QString());

	m_ui.MergerNodesListWidget->setFocus();

	changedMergerNodes();
}


void qpwgraph_options::removeMergerNodes (void)
{
	const int i	= m_ui.MergerNodesListWidget->currentRow();
	if (i < 0)
		return;

	QListWidgetItem *item = m_ui.MergerNodesListWidget->takeItem(i);
	if (item)
		delete item;

	changedMergerNodes();
}


void qpwgraph_options::clearMergerNodes (void)
{
	m_ui.MergerNodesListWidget->clear();

	changedMergerNodes();
}


// Stabilize current form state.
void qpwgraph_options::stabilize (void)
{
#ifdef CONFIG_SYSTEM_TRAY
	const bool systray = m_ui.SystemTrayEnabledCheckBox->isChecked();
	m_ui.SystemTrayQueryCloseCheckBox->setEnabled(systray);
	m_ui.SystemTrayStartMinimizedCheckBox->setEnabled(systray);
#endif

	if (m_ui.FilterNodesEnabledCheckBox->isChecked()) {
		m_ui.FilterNodesNameComboBox->setEnabled(true);
		m_ui.FilterNodesListWidget->setEnabled(true);
		const QString& node_name
			= m_ui.FilterNodesNameComboBox->currentText();
		m_ui.FilterNodesAddToolButton->setEnabled(!node_name.isEmpty() &&
			m_ui.FilterNodesListWidget->findItems(node_name, Qt::MatchFixedString).isEmpty());
		const int i	= m_ui.FilterNodesListWidget->currentRow();
		m_ui.FilterNodesRemoveToolButton->setEnabled(i >= 0);
		m_ui.FilterNodesClearToolButton->setEnabled(
			m_ui.FilterNodesListWidget->count() > 0);
	} else {
		m_ui.FilterNodesNameComboBox->setEnabled(false);
		m_ui.FilterNodesListWidget->setEnabled(false);
		m_ui.FilterNodesAddToolButton->setEnabled(false);
		m_ui.FilterNodesRemoveToolButton->setEnabled(false);
		m_ui.FilterNodesClearToolButton->setEnabled(false);
	}

	if (m_ui.MergerNodesEnabledCheckBox->isChecked()) {
		m_ui.MergerNodesNameComboBox->setEnabled(true);
		m_ui.MergerNodesListWidget->setEnabled(true);
		const QString& node_name
			= m_ui.MergerNodesNameComboBox->currentText();
		m_ui.MergerNodesAddToolButton->setEnabled(!node_name.isEmpty() &&
			m_ui.MergerNodesListWidget->findItems(node_name, Qt::MatchFixedString).isEmpty());
		const int i	= m_ui.MergerNodesListWidget->currentRow();
		m_ui.MergerNodesRemoveToolButton->setEnabled(i >= 0);
		m_ui.MergerNodesClearToolButton->setEnabled(
			m_ui.MergerNodesListWidget->count() > 0);
	} else {
		m_ui.MergerNodesNameComboBox->setEnabled(false);
		m_ui.MergerNodesListWidget->setEnabled(false);
		m_ui.MergerNodesAddToolButton->setEnabled(false);
		m_ui.MergerNodesRemoveToolButton->setEnabled(false);
		m_ui.MergerNodesClearToolButton->setEnabled(false);
	}

	m_ui.DialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(m_dirty > 0);
}


// end of qpwgraph_options.cpp
