#include "StdAfx.h"
#include "CrossSectionConfigDlg.h"

#include "View3D.h"



CrossSectionConfigDlg::CrossSectionConfigDlg(QWidget *parent)
	: QDialog(parent)
{
	ui.setupUi(this);

	Qt::WindowFlags flags = windowFlags() & (~Qt::WindowContextHelpButtonHint);
	flags = flags | Qt::WindowMinimizeButtonHint;
	flags = flags | Qt::WindowCloseButtonHint;
	setWindowFlags(flags);

	UpdateSlideEnabled();
}

CrossSectionConfigDlg::~CrossSectionConfigDlg()
{
}

void CrossSectionConfigDlg::keyPressEvent(QKeyEvent *e)
{
	bool Alt   = ( ( e->modifiers() & Qt::AltModifier     ) != 0 );
	bool Shift = ( ( e->modifiers() & Qt::ShiftModifier   ) != 0 );
	bool Ctrl  = ( ( e->modifiers() & Qt::ControlModifier ) != 0 );

	if(e->key() == Qt::Key_Escape)
	{
		close();
		return;
	}

	if(!Ctrl && !Shift && !Alt)
	{
		if(e->key() == Qt::Key_T)
		{
			ui.checkTopMost->setChecked(!ui.checkTopMost->isChecked());
		}
	}
}

void CrossSectionConfigDlg::InitializeConfigDlg(View3D* view3d)
{
	m_View3D = view3d;

	const CrossSectionConfig* conf = GetCSConfig();

	SetSliderValueSilentN(ui.sliderCrossSectionPointX, conf->m_CutPosX);
	SetSliderValueSilentN(ui.sliderCrossSectionPointY, conf->m_CutPosY);
	SetSliderValueSilentN(ui.sliderCrossSectionPointZ, conf->m_CutPosZ);

	ui.checkCorssSection->blockSignals(true);
	ui.checkCorssSection->setChecked(conf->m_Enable);
	ui.checkCorssSection->blockSignals(false);

	SetSliderValueSilentN(ui.sliderCrossSectionRibbonHeight, conf->m_RibbonRange);

	ui.checkCorssSectionRibbon->blockSignals(true);
	ui.checkCorssSectionRibbon->setChecked(conf->m_Ribbon);
	ui.checkCorssSectionRibbon->blockSignals(false);

	UpdateValueLabels();
}

void CrossSectionConfigDlg::SetSliderValueSilentN(QSlider* s, float val)
{
	int cs_pos = (int)((float)s->maximum() * val);
	SetSliderValueSilent(s, cs_pos);
}

void CrossSectionConfigDlg::SetSliderValueSilent(QSlider* s, int val)
{
	s->blockSignals(true);
	s->setValue(val);
	s->blockSignals(false);
}

void CrossSectionConfigDlg::on_checkTopMost_toggled(bool checked)
{
	Qt::WindowFlags flags = windowFlags();
	if (checked)
	{
		setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint);
	}
	else
	{
		setWindowFlags(flags ^ (Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint));
	}

	show();
}

void CrossSectionConfigDlg::UpdateValueLabels(void)
{
	ui.labelCrossSectionPointX->setText(QString::number(GetCSPosValueX()));
	ui.labelCrossSectionPointY->setText(QString::number(GetCSPosValueY()));
	ui.labelCrossSectionPointZ->setText(QString::number(GetCSPosValueZ()));

	QString CsRibbon = QString::number(GetRibbonRange());
	ui.labelCrossSectionRibbonHeight->setText(CsRibbon);
}

float CrossSectionConfigDlg::GetSliderValueSilentN(const QSlider* s) const
{
	return (float)s->value() / (float)s->maximum();
}

float CrossSectionConfigDlg::GetCSPosValueX(void) const
{
	return GetSliderValueSilentN(ui.sliderCrossSectionPointX);
}

float CrossSectionConfigDlg::GetCSPosValueY(void) const
{
	return GetSliderValueSilentN(ui.sliderCrossSectionPointY);
}

float CrossSectionConfigDlg::GetCSPosValueZ(void) const
{
	return GetSliderValueSilentN(ui.sliderCrossSectionPointZ);
}

float CrossSectionConfigDlg::GetRibbonRange(void) const
{
	int max_val = ui.sliderCrossSectionRibbonHeight->maximum();
	int val = ui.sliderCrossSectionRibbonHeight->value();
	return (float)val / (float)max_val;
}


CrossSectionConfig* CrossSectionConfigDlg::GetCSConfig(void)
{
	return &GetScene()->m_CrossSectionConfig;
}

const CrossSectionConfig* CrossSectionConfigDlg::GetCSConfig(void) const
{
	return &GetScene()->m_CrossSectionConfig;
}


void CrossSectionConfigDlg::on_sliderCrossSectionPointX_valueChanged(int value)
{
	UpdatePosition(GetCSConfig()->m_CutPosX, GetCSPosValueX());
}

void CrossSectionConfigDlg::on_sliderCrossSectionPointY_valueChanged(int value)
{
	UpdatePosition(GetCSConfig()->m_CutPosY, GetCSPosValueY());
}

void CrossSectionConfigDlg::on_sliderCrossSectionPointZ_valueChanged(int value)
{
	UpdatePosition(GetCSConfig()->m_CutPosZ, GetCSPosValueZ());
}

void CrossSectionConfigDlg::UpdatePosition(float& dst, float cutpos)
{
	UpdateValueLabels();

	float pre_pos = dst;
	dst = cutpos;

	if (ui.checkSyncCamera->isChecked())
		SyncCameraMove(cutpos - pre_pos);

	UpdateCS(true);
}

void CrossSectionConfigDlg::SyncCameraMove(float diff)
{
	SceneMain* scene = m_View3D->m_Scene;

	lm::range3f r = scene->GetSceneBBox();
	if (!r.is_valid())
		return;

	lib_gl::CameraManipulator& manip = m_View3D->m_Camera.m_Manip;
	lm::vec3f n = GetCSConfig()->GetCutAxis();

	lm::vec3f d(n.x * r.length_x(), n.y * r.length_y(), n.z * r.length_z());

	lm::vec3f p0 = scene->m_WorldTransform.TransformVec(lm::vec3f::get_zero());
	lm::vec3f p1 = scene->m_WorldTransform.TransformVec(d);

	manip.Translate((p1 - p0) * diff);
}

void CrossSectionConfigDlg::on_checkCorssSection_toggled(bool checked)
{
	GetCSConfig()->m_Enable = checked;
	UpdateCS(false);
}

void CrossSectionConfigDlg::on_sliderCrossSectionRibbonHeight_valueChanged(int value)
{
	UpdateValueLabels();

	float range = GetRibbonRange();
	GetCSConfig()->m_RibbonRange = GetRibbonRange();

	UpdateCS(false);
}

void CrossSectionConfigDlg::on_checkCorssSectionRibbon_toggled(bool checked)
{
	GetCSConfig()->m_Ribbon = checked;
	UpdateCS(false);
}

void CrossSectionConfigDlg::on_checkLineCS_toggled(bool checked)
{
	GetCSConfig()->m_LineCS = checked;
	UpdateCS(true);
}

void CrossSectionConfigDlg::on_radioDirX_toggled(bool)
{
	CutAngleChanged();
}

void CrossSectionConfigDlg::on_radioDirY_toggled(bool)
{
	CutAngleChanged();
}

void CrossSectionConfigDlg::on_radioDirZ_toggled(bool)
{
	CutAngleChanged();
}

void CrossSectionConfigDlg::on_radioFreeCut_toggled(bool)
{
	CutAngleChanged();
}

void CrossSectionConfigDlg::on_checkClipRev_toggled(bool)
{
	CutAngleChanged();
}

void CrossSectionConfigDlg::CutAngleChanged(void)
{
	CrossSectionConfig* config = GetCSConfig();

	if (ui.radioFreeCut->isChecked())
	{
		config->SetFreeCut();
	}
	else
	{
		bool fore = !ui.checkClipRev->isChecked();
		if (ui.radioDirX->isChecked())
			config->SetAxisCut(AxisType::X, fore);
		if (ui.radioDirY->isChecked())
			config->SetAxisCut(AxisType::Y, fore);
		if (ui.radioDirZ->isChecked())
			config->SetAxisCut(AxisType::Z, fore);
	}

	UpdateSlideEnabled();

	UpdateCS(true);
}

void CrossSectionConfigDlg::UpdateSlideEnabled(void)
{
	ui.sliderCrossSectionPointX->setEnabled(ui.radioDirX->isChecked());
	ui.sliderCrossSectionPointY->setEnabled(ui.radioDirY->isChecked());
	ui.sliderCrossSectionPointZ->setEnabled(ui.radioDirZ->isChecked());

	ui.labelCrossSectionPointX->setEnabled(ui.sliderCrossSectionPointX->isEnabled());
	ui.labelCrossSectionPointY->setEnabled(ui.sliderCrossSectionPointY->isEnabled());
	ui.labelCrossSectionPointZ->setEnabled(ui.sliderCrossSectionPointZ->isEnabled());
}

void CrossSectionConfigDlg::on_checkMultiColor_toggled(bool checked)
{
	GetCSConfig()->m_MultiColor = checked;
	UpdateCS(false);
}


void CrossSectionConfigDlg::on_checkShowCrossSectionLength_toggled(bool checked)
{
	GetCSConfig()->m_EnableShowLength = checked;
	UpdateCS(true);
}

void CrossSectionConfigDlg::on_checkShowCrossSectionCHLength_toggled(bool checked)
{
	GetCSConfig()->m_EnableShowCHLength = checked;
	UpdateCS(true);
}

void CrossSectionConfigDlg::on_checkLengthWhole_toggled(bool checked)
{
	GetCSConfig()->m_EnableCrossSectionGroup = !checked;
	UpdateCS(true);
}

void CrossSectionConfigDlg::on_checkShowConvexHull_toggled(bool checked)
{
	GetCSConfig()->m_EnableConvexHull = checked;
	UpdateCS(true);
}

void CrossSectionConfigDlg::on_checkShowCutPlane_toggled(bool checked)
{
	GetCSConfig()->m_ShowCutplane = checked;
	UpdateCS(false);
}

void CrossSectionConfigDlg::on_checkTransparent_toggled(bool checked)
{
	GetCSConfig()->m_Transparent = checked;
	UpdateCS(false);
}


void CrossSectionConfigDlg::UpdateCS(bool EnableUpateExt)
{
	if (EnableUpateExt)
		GetScene()->UpdateCrossSectionIfRequire(false);

	emit ConfigChanged();
}


SceneMain* CrossSectionConfigDlg::GetScene(void)
{
	return m_View3D->m_Scene;
}

const SceneMain* CrossSectionConfigDlg::GetScene(void) const
{
	return m_View3D->m_Scene;
}

void CrossSectionConfigDlg::on_buttonAddRecord_clicked()
{
	GetScene()->AddCrossSectionRecord();
	emit ConfigChanged();
}

void CrossSectionConfigDlg::on_buttonDelRecord_clicked()
{
	GetScene()->ClearCrossSectionRecord();
	emit ConfigChanged();
}
