/*
	Copyright (C) 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"



TerraView::TerraView ( MainWindow & mainwindow )
	:
	QOpenGLWidget	( &mainwindow ),
	m_mainwindow	( mainwindow ),
	m_last_pos	( QPoint(0,0) )
{
	setMinimumSize ( 200, 200 );

	// Enable antialiasing samples
	QSurfaceFormat fmt = format ();
	fmt.setSamples ( 7 );
	fmt.setSwapBehavior ( QSurfaceFormat::TripleBuffer );
	setFormat ( fmt );
}

void TerraView::initializeGL ()
{
	initializeOpenGLFunctions ();

/*
	m_mainwindow.scene().init_buffers ( m_mainwindow.map() );
*/
}

void TerraView::paintGL ()
{
	m_mainwindow.scene().render ( m_camera );
}

void TerraView::resizeGL ( int const width, int const height )
{
	m_camera.set_view_geometry ( width, height, m_gl_range );
}

void TerraView::mousePressEvent ( QMouseEvent * const event )
{
	if ( 0 == m_mbutton_down )
	{
		m_last_pos = event->pos ();
		m_mbutton_down = 1;
	}

	setFocus ( Qt::OtherFocusReason );
}

void TerraView::mouseReleaseEvent ( QMouseEvent * const event )
{
	m_last_pos = event->pos ();

	if ( (event->buttons () & Qt::RightButton)
		|| (event->buttons () & Qt::LeftButton)
		)
	{
		m_mbutton_down = 1;
	}
	else
	{
		m_mbutton_down = 0;
	}

	setFocus ( Qt::OtherFocusReason );
}

void TerraView::mouseMoveEvent ( QMouseEvent * const event )
{
	setFocus ( Qt::OtherFocusReason );

	int const scale = (event->modifiers() & Qt::ShiftModifier) ? 10 : 1;
	int const mx = event->x ();
	int const my = event->y ();
	TerraCamera & cam = m_camera;
	int const dx = mx - m_last_pos.x();
	int const dy = my - m_last_pos.y();

	m_last_pos = event->pos ();

	if ( (event->buttons () & Qt::LeftButton) )
	{
		double const nudge = cam.get_nudge() * scale;

		cam.move ( -dx * nudge, dy * nudge, 0 );
	}
	else if ( (event->buttons () & Qt::RightButton) )
	{
		double const nudge = scale / 8.0 / 4.0;

		cam.turn ( dy * nudge, 0, -dx * nudge );
	}
	else
	{
		return;		// Nothing to do
	}

	// Update the rendered OpenGL
	update();
}

void TerraView::keyPressEvent ( QKeyEvent * const event )
{
	int const scale = (event->modifiers() & Qt::ShiftModifier) ? 10 : 1;
	int const ctrl = (event->modifiers() & Qt::ControlModifier) ? 1 : 0;
	TerraCamera & cam = m_camera;

	if ( ctrl )
	{
		// Control key pressed

		double const nudge = (double)scale / 8.0;

		switch ( event->key() )
		{
		case Qt::Key_Up:
			cam.turn ( nudge, 0, 0 );
			break;

		case Qt::Key_Down:
			cam.turn ( -nudge, 0, 0 );
			break;

		case Qt::Key_Left:
			cam.turn ( 0, 0, -nudge );
			break;

		case Qt::Key_Right:
			cam.turn ( 0, 0, nudge );
			break;
		}
	}
	else
	{
		// Control key *NOT* pressed

		double const nudge = cam.get_nudge() * scale;

		switch ( event->key() )
		{
		case Qt::Key_PageUp:
			cam.move ( 0, 0, nudge );
			break;

		case Qt::Key_PageDown:
			cam.move ( 0, 0, -nudge );
			break;

		case Qt::Key_Up:
			cam.move ( 0, nudge, 0 );
			break;

		case Qt::Key_Down:
			cam.move ( 0, -nudge, 0 );
			break;

		case Qt::Key_Left:
			cam.move ( -nudge, 0, 0 );
			break;

		case Qt::Key_Right:
			cam.move ( nudge, 0, 0 );
			break;

		case Qt::Key_F1:
			printf ( "x=%.15g y=%.15g z=%.15g "
				"xrot=%.15g yrot=%.15g zrot=%.15g\n",
				cam.get_x(), cam.get_y(),
				cam.get_z(),
				cam.get_rot_x(), cam.get_rot_y(),
				cam.get_rot_z() );
			break;

		case Qt::Key_F5:
			m_mainwindow.press_change_mode();
			break;
		}
	}

	switch ( event->key() )
	{
	case Qt::Key_Escape:
	case Qt::Key_Q:
		m_mainwindow.press_quit();
		break;

	case Qt::Key_S:
		m_mainwindow.output_image_file ();
		break;

	case Qt::Key_Home:
		move_camera_home ( ctrl );
		break;

	case Qt::Key_End:
		cam.turn_around ();
		break;
	}

	// Update the rendered OpenGL
	update();
}

void TerraView::move_camera_home ( int const top )
{
	TerraCamera & cam = m_camera;

	if ( top )
	{
		cam.set_position ( 0, 0, -3000 );
		cam.set_angle ( 0, 0, 0 );
	}
	else
	{
		cam.set_position ( 1180, -1600, 910 );
//		cam.set_position ( -327, -207, 160 );

//		cam.set_position ( -1100, 1900, -700 );
//		cam.set_position ( 1100, 1900, -700 );
//		cam.set_position ( 1100, -1900, -700 );
//		cam.set_position ( -1100, -1900, -700 );

//		cam.set_angle ( 245, 0, 325 );
//		cam.set_angle ( 252, 0, 325 );

		cam.look_at ( {0,0,0} );
//		cam.look_at ( {0, -100, 1000} );

/*
		cam.look_at ( {LANDSCAPE_VIEW_RANGE * 0.5,
			LANDSCAPE_VIEW_RANGE * 0.5,
			LANDSCAPE_VIEW_RANGE * 0.7} );
//*/
	}
}

