/*
	Copyright (C) 2022-2024 Mark Tyler

	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 3 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 in the file COPYING.
*/

#include "qt5.h"



int main (
	int			const	argc,
	char	const * const * const	argv
	)
{
	CommandLine cline;

	if ( cline.parse ( argc, argv ) )
	{
		return cline.exit().value ();
	}

	// I don't want Qt snooping or changing my command line.
	int		dummy_argc	= 1;
	char		dummy_str[1]	= { 0 };
	char		* dummy_argv	= dummy_str;
	QApplication	app ( dummy_argc, &dummy_argv );
	MainWindow	window ( cline );

	if ( 0 == cline.exit().value () )
	{
		app.exec ();
	}

	return cline.exit().value ();
}

MainWindow::MainWindow ( CommandLine & cline )
	:
	uprefs		( cline.userprefs() ),
	mprefs		( cline.get_memprefs() ),
	m_ui_float	( *this ),
	m_ui_double	( *this ),
	m_ui_integer	( *this ),
	m_ui_rational	( *this )
{
	setWindowTitle ( VERSION );

	std::string path;
	mtKit::get_data_dir ( path, DATA_INSTALL "/icons/hicolor/scalable/apps/"
		BIN_NAME ".svg" );
	setWindowIcon ( QIcon ( path.c_str () ) );

	QWidget * widget = new QWidget;
	setCentralWidget ( widget );

	create_menu ();

	QVBoxLayout * vbox_main = new QVBoxLayout;
	widget->setLayout ( vbox_main );

	QTabWidget * tabWidget = new QTabWidget;
	vbox_main->addWidget ( tabWidget );

///	Calculator tabs --------------------------------------------------------

	m_ui_float.build ( tabWidget );
	m_ui_double.build ( tabWidget );
	m_ui_integer.build ( tabWidget );
	m_ui_rational.build ( tabWidget );

/// ----------------------------------------------------------------------------

	setMinimumSize ( 160, 160 );
	setGeometry ( mprefs.window_x, mprefs.window_y,
		mprefs.window_w, mprefs.window_h );

	if ( 1 == mprefs.window_maximized )
	{
		showMaximized ();
	}
	else
	{
		show ();
	}
}

MainWindow::~MainWindow ()
{
	if ( isMaximized () )
	{
		uprefs.set ( PREFS_WINDOW_MAXIMIZED, 1 );
	}
	else
	{
		uprefs.set ( PREFS_WINDOW_MAXIMIZED, 0 );

		uprefs.set ( PREFS_WINDOW_X, geometry().x () );
		uprefs.set ( PREFS_WINDOW_Y, geometry().y () );
		uprefs.set ( PREFS_WINDOW_W, geometry().width () );
		uprefs.set ( PREFS_WINDOW_H, geometry().height () );
	}
}



/// ----------------------------------------------------------------------------



std::string choose_output_filename (
	QWidget		* const	parent,
	char	const * const	title
	)
{
	mtQEX::SaveFileDialog dialog ( parent, title );

	// Loop until successful save or user cancel
	while ( dialog.exec () )
	{
		QString filename = mtQEX::get_filename ( dialog );

		if ( filename.isEmpty () )
		{
			continue;
		}

		return filename.toStdString();
	}

	return "";
}

void report_file_error (
	QWidget		* const	parent,
	char	const * const	message,
	std::string	const	& filename
	)
{
	std::string txt ( message );

	txt += '\n';
	txt += filename;

	QMessageBox::critical ( parent, "Error", mtQEX::qstringFromC (
		txt.c_str() ) );
}



/// ----------------------------------------------------------------------------



template < typename Tparser >
void MainWindow::TabUIelements<Tparser>::build ( QTabWidget * const tabWidget )
{
	QWidget		* tab, * w;
	QVBoxLayout	* vbox;
	QGridLayout	* grid;
	QGroupBox	* groupBox;
	QVBoxLayout	* sgvb;
	QHBoxLayout	* hbox;
	QPushButton	* button;

	tab = new QWidget;
	tabWidget->addTab ( tab,
		(std::is_same<Tparser, mtDW::FloatParser>::value)
			? TEXT_TITLE_FLOAT :
		(std::is_same<Tparser, mtDW::DoubleParser>::value)
			? TEXT_TITLE_DOUBLE :
		(std::is_same<Tparser, mtDW::IntegerParser>::value)
			? TEXT_TITLE_INTEGER :
		(std::is_same<Tparser, mtDW::RationalParser>::value)
			? TEXT_TITLE_RATIONAL :
		TEXT_TITLE_ERROR
		);

	vbox = new QVBoxLayout;
	tab->setLayout ( vbox );

	w = new QWidget;
	vbox->addWidget ( w );

	grid = new QGridLayout;
	w->setLayout ( grid );

	groupBox = new QGroupBox ( "Input" );
	grid->addWidget ( groupBox, 0, 0 );

	sgvb = new QVBoxLayout;
	groupBox->setLayout ( sgvb );

	m_text_input = new QPlainTextEdit;
	sgvb->addWidget ( m_text_input );

	groupBox = new QGroupBox ( "Output" );
	m_group_box = groupBox;
	grid->addWidget ( groupBox, 0, 1 );

	sgvb = new QVBoxLayout;
	groupBox->setLayout ( sgvb );

	m_text_output = new QPlainTextEdit;
	sgvb->addWidget ( m_text_output );
	m_text_output->setReadOnly ( true );

// Buttons ----------------------------------------------------------------

	w = new QWidget;
	vbox->addWidget ( w );

	hbox = new QHBoxLayout;
	w->setLayout ( hbox );

	button = new QPushButton ( QIcon::fromTheme ( "view-refresh" ),
		"&Evaluate" );
	button->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Preferred );
	hbox->addWidget ( button );
	connect ( button, &QPushButton::clicked, [this]()
		{
			click_evaluate ();
		});

	button = new QPushButton ( "Show Variables" );
	button->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Preferred );
	hbox->addWidget ( button );
	connect ( button, &QPushButton::clicked, [this]()
		{
			click_show_vars ();
		});

	button = new QPushButton ( "Show Functions" );
	button->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Preferred );
	hbox->addWidget ( button );
	connect ( button, &QPushButton::clicked, [this]()
		{
			click_show_funcs ();
		});

	button = new QPushButton ( QIcon::fromTheme ( "edit-copy" ),
		"Copy Output" );
	button->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Preferred );
	hbox->addWidget ( button );
	connect ( button, &QPushButton::clicked, [this]()
		{
			QApplication::clipboard()->setText (
				m_text_output->toPlainText() );
		});

	button = new QPushButton ( QIcon::fromTheme ( "document-save" ),
		"Save Output" );
	button->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Preferred );
	hbox->addWidget ( button );
	connect ( button, &QPushButton::clicked, [this]()
		{
			std::string const filename = choose_output_filename (
				&mainwindow, "Save number" );

			save_a_number( &mainwindow, m_parser.result(), filename);
		});

	// Squashes buttons together to the left
	hbox->addWidget ( new QWidget );
}

template void MainWindow::TabUIelements<mtDW::FloatParser>::build ( QTabWidget * tabWidget );
template void MainWindow::TabUIelements<mtDW::DoubleParser>::build ( QTabWidget * tabWidget );
template void MainWindow::TabUIelements<mtDW::IntegerParser>::build ( QTabWidget * tabWidget );
template void MainWindow::TabUIelements<mtDW::RationalParser>::build ( QTabWidget * tabWidget );

