/*
	Copyright (C) 2021-2025 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 "lanter_qt.h"



MainWindow::MainWindow ( CommandLine & cline )
	:
	m_cline		( cline ),
	m_uprefs	( cline.userprefs() ),
	m_mprefs	( cline.get_memprefs() ),
	m_animate	( cline )
{
	setWindowTitle ( BIN_NAME " - " VERSION );

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

	QVBoxLayout * vbox_main = new QVBoxLayout;
	vbox_main->setSpacing ( 0 );
	vbox_main->setContentsMargins ( 0, 0, 0, 0 );
	w->setLayout ( vbox_main );

	m_map.set_seed ( (uint64_t)m_cline.get_map_seed () );
	if ( init_map () )
	{
		close();
		throw 123;
	}

	QSplitter * split = new QSplitter ( Qt::Horizontal );
	vbox_main->addWidget ( split );

	m_terraview_a = new TerraView ( *this );
	split->addWidget ( m_terraview_a );

	m_terraview_b = new TerraView ( *this );
	split->addWidget ( m_terraview_b );

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

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

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

	// show() above makes the GL initialized and ready for the buffer prep
	m_scene.init_buffers ( m_map );

	int const ow = m_cline.get_output_width();
	int const oh = m_cline.get_output_height();
	if ( ow >= OUTPUT_WH_MIN && ow <= OUTPUT_WH_MAX
		&& oh >= OUTPUT_WH_MIN && oh <= OUTPUT_WH_MAX
		)
	{
		m_terraview_a->setFixedSize ( ow, oh );
	}

	m_terraview_a->move_camera_home (0);
	m_terraview_b->move_camera_home (1);
	m_terraview_a->setFocus ( Qt::OtherFocusReason );

	if ( 0 == m_animate.init () )
	{
		set_mode ( MODE_ANIMATION );

		for ( int f = 0; ; f++ )
		{
			mtQEX::process_qt_pending ();

			if ( m_animate.prepare_frame ( f )
				|| ! this->isVisible()
				)
			{
				press_quit ();
				m_cline.exit().set_value ( 1 );
				break;
			}

			TerraCamera & cam = m_terraview_a->camera();
			cam.set_position( m_animate.get_position() );
			cam.look_at ( m_animate.get_focus() );

			m_terraview_a->update();

			m_animate.save_frame( f, [this]
				(std::string const & filename)
				{
					return this->export_image ( filename );
				});
		}
	}
	else
	{
		set_mode ( MODE_INTERACTIVE );
	}
}

void MainWindow::store_window_geometry ()
{
	if ( isMaximized () )
	{
		m_uprefs.set ( PREFS_WINDOW_MAXIMIZED, 1 );
	}
	else
	{
		m_uprefs.set ( PREFS_WINDOW_MAXIMIZED, 0 );

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

void MainWindow::closeEvent ( QCloseEvent * const ev )
{
	if ( isEnabled () == false )
	{
		// Main window is currently disabled so ignore all requests
		ev->ignore ();
		return;
	}

	ev->accept ();
	store_window_geometry ();
}

void MainWindow::press_quit ()
{
	this->close();
}

void MainWindow::press_change_mode ()
{
	m_scene.next_mode();
	m_terraview_a->update();
	m_terraview_b->update();
}

int MainWindow::export_image ( std::string const & filename )
{
	if ( m_cline.get_verbose() )
	{
		std::cout << filename << "\n";
	}

	QPixmap qp = m_terraview_a->grab();

	if ( ! qp.save ( filename.c_str() ) )
	{
		std::cerr << "export_image: Unable to save pixmap\n";
		return 1;
	}

	return 0;
}

void MainWindow::output_image_file ()
{
	char buf[256];
	TerraCamera & cam = m_terraview_a->camera();
	snprintf ( buf, sizeof(buf), BIN_NAME "_%.15g_%.15g_%.15g.png",
		cam.get_x(),
		cam.get_y(),
		cam.get_z() );

	std::string filename ( mtkit_file_home () );

	filename += MTKIT_DIR_SEP;
	filename += buf;

	export_image ( filename );
}

int MainWindow::init_map ()
{
	if ( m_map.create_landscape ( m_cline.get_map_size () ) )
	{
		std::cerr << "!!!\n";
		return 1;
	}

	char	const * const	filename = m_cline.get_save_map ();

	if ( filename )
	{
		if ( m_map.save_tsv ( filename ) )
		{
			std::cerr << "!!!\n";
			return 1;
		}
	}

	return 0;
}

void MainWindow::set_mode ( int const mode )
{
	m_mode = mode;
}

