#include "main_window.h"
#include "mesh_processor.h"
#include "double_input.h"

#include <QApplication>
#include <QFileDialog>
#include <QMenuBar>
#include <QGroupBox>
#include <QPushButton>
#include <QSlider>
#include <QLabel>


MainWindow::MainWindow(QWidget *parent)
	:QMainWindow(parent),
	 toolbar(this),
	 mesh_viewer() {
	setCentralWidget(&mesh_viewer);

	QMenuBar *menu_bar = new QMenuBar();
	setMenuBar(menu_bar);

	// File menu
	QMenu *file_menu = new QMenu("Fichier");
	open_action = file_menu->addAction("Ouvrir…", [&](){
		emit open(QFileDialog::getOpenFileName(this, "Ouvrir un maillage"));
	});
	save_action = file_menu->addAction("Enregistrer sous…", [&]() {
		emit save(QFileDialog::getSaveFileName(this,
											   "Enregistrer un maillage"));
	});
	menu_bar->addMenu(file_menu);
	if (!mesh_viewer.isInitialized()) {
		open_action->setEnabled(false);
		connect(&mesh_viewer, &MeshViewer::initialized, [&]() {
			open_action->setEnabled(true);
		});
	}

	addToolBar(Qt::RightToolBarArea, &toolbar);

	// Hole filling tools
	QGroupBox *hole_box = new QGroupBox("Remplissage de trous");
	QGridLayout *hole_layout = new QGridLayout();
	hole_box->setLayout(hole_layout);

	QPushButton *fill_holes_dumb = new QPushButton("Remplir bêtement");
	connect(fill_holes_dumb, &QPushButton::clicked,
			this, &MainWindow::fillHolesDumbClicked);
	hole_layout->addWidget(fill_holes_dumb, 0, 0);

	QPushButton *fill_holes_implicit =
		new QPushButton("Remplir par une surface implicite");
	connect(fill_holes_implicit, &QPushButton::clicked,
			this, &MainWindow::fillHolesImplicitClicked);
	hole_layout->addWidget(fill_holes_implicit, 1, 0);

	QLabel *implicit_scale_text =
		new QLabel("Échelle du remplissage implicite", this);
	hole_layout->addWidget(implicit_scale_text, 2, 0);
	fill_holes_implicit_scale = new DoubleInput(this, 0, 10, 4);
	connect(fill_holes_implicit_scale, &DoubleInput::valueChanged,
			this, &MainWindow::fillHolesImplicitScaleChanged);
	hole_layout->addWidget(fill_holes_implicit_scale->slider(), 3, 0);
	hole_layout->addWidget(fill_holes_implicit_scale->spinBox(), 3, 1);

	QLabel *implicit_discr_text =
		new QLabel("Taux de discrétisation du remplissage implicite", this);
	hole_layout->addWidget(implicit_discr_text, 4, 0);
	fill_holes_implicit_discr = new DoubleInput(this, .02, .1, 1/40.);
	connect(fill_holes_implicit_discr, &DoubleInput::valueChanged,
			this, &MainWindow::fillHolesImplicitDiscrChanged);
	hole_layout->addWidget(fill_holes_implicit_discr->slider(), 5, 0);
	hole_layout->addWidget(fill_holes_implicit_discr->spinBox(), 5, 1);

	toolbar.addWidget(hole_box);


	// Smoothing tools
	QGroupBox *smooth_box = new QGroupBox("Adoucissement");
	QGridLayout *smooth_layout = new QGridLayout();
	smooth_box->setLayout(smooth_layout);
	QPushButton *smooth = new QPushButton("Adoucir (uniforme)");
	connect(smooth, &QPushButton::clicked,
			this, &MainWindow::smoothUniformClicked);
	smooth_layout->addWidget(smooth, 1, 0);
	QPushButton *smooth_cotan = new QPushButton("Adoucir (cotangent)");
	smooth_cotangent_factor_input =
		new DoubleInput(this, .00001, .001, .0001);
	connect(smooth_cotangent_factor_input, &DoubleInput::valueChanged,
			[&](double value) { smooth_cotangent_factor = value; });
	connect(smooth_cotan, &QPushButton::clicked,
			[&]() { emit smoothCotangentClicked(smooth_cotangent_factor); });
	smooth_layout->addWidget(smooth_cotan, 2, 0);
	QLabel *smooth_cotan_text =
		new QLabel("Facteur de l'adoucissement cotangentiel", this);
	smooth_layout->addWidget(smooth_cotan_text, 3, 0);
	smooth_layout->addWidget(smooth_cotangent_factor_input->slider(), 4, 0);
	QDoubleSpinBox *sb = (QDoubleSpinBox *)(smooth_cotangent_factor_input->spinBox());
	sb->setDecimals(5);
	smooth_layout->addWidget(smooth_cotangent_factor_input->spinBox(), 4, 1);
	toolbar.addWidget(smooth_box);


	// Curvature tools
	QGroupBox *curvature_box = new QGroupBox("Analyse de courbure");
	QLayout *curvature_layout = new QVBoxLayout();
	curvature_box->setLayout(curvature_layout);
	QPushButton *patch_mode = new QPushButton(
		"Afficher le patch de la sélection");
	patch_mode->setCheckable(true);
	connect(patch_mode, &QPushButton::toggled,
			this, &MainWindow::patchViewToggled);
	curvature_layout->addWidget(patch_mode);
	toolbar.addWidget(curvature_box);
}
