/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/

// EvalSurfZebraTool.cpp: MGEvalSurfZebraTool クラスのインプリメンテーション
#include "stdafx.h"
#include "tl2/TL2Triangles.h"
#include "fugen.h"
#include "fugenView.h"
#include "Misc/UserPreference.h"
#include "EvalCmd/EvalSurfZebraTool.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

// MGEvalSurfZebraTool
MGEvalSurfZebraTool::MGEvalSurfZebraTool(fugenDoc* pDoc)
: MGSelectState(pDoc, ID_EVAL_SURFACE_ZEBRA,
 MGSelectState::MULTIPLE_SELECT, // multiple selection
 mgAll_2Manifold){
	// ダイアログを準備する
	attachModelessDialogue<CZebraDlg>(this);
}

MGCommandBase* MGEvalSurfZebraTool::initial_clone(fugenDoc* pDoc)const{
	return new MGEvalSurfZebraTool(pDoc);
}

bool MGEvalSurfZebraTool::initiate_tool(){
	MGSelectState::initiate_tool();
	const UserPreference& pref = UserPreference::getInstance();
	m_color = pref.GetIntValue(upv_Eval_SurfZebra_Color);
	m_dThickness = float(pref.GetDoubleValue(upv_Eval_SurfZebra_Thickness));
	m_bVertical = pref.GetBoolValue(upv_Eval_SurfZebra_Vertical);

	if(is_breaking_command()){
		current_objects().select_fsurfaces(m_objectives);
		draw_pictures();
		return true;
	}

	if(resetCurrentObjects(mgAll_2Manifold)){
		MGPickObjects unselected;
		OnSelected(0, m_objectives, unselected);
		return false;
	}else{
		clear_pick_object();
		// 最初のメッセージ
		SetStatusMessage(IDS_PROMPT_SURFACE);
		return false;
	}
}

bool MGEvalSurfZebraTool::terminate_tool(bool cancel){
	UserPreference& pref = UserPreference::getInstance();
	pref.SetIntValue(upv_Eval_SurfZebra_Color, m_color);
	pref.SetDoubleValue(upv_Eval_SurfZebra_Thickness, m_dThickness);
	pref.SetBoolValue(upv_Eval_SurfZebra_Vertical, m_bVertical);

	return MGSelectState::terminate_tool(cancel);
}

bool MGEvalSurfZebraTool::OnCommandEnd(
	UINT nIDS,	//=0: erase the current message, and display no messages.
				//=1: display "xxxx" normally end.
				//otherwise: nIDS is a string id, and load the message from string table to display.
	bool erase_temporary_display
){
	return MGSelectState::OnCommandEnd(1,false);//Zebra stays displayed.
}

bool MGEvalSurfZebraTool::OnSelected(
	fugenView* window,//The fugenView pointer where point input event took place.
	MGPickObjects&	objs,	//selected objects at this selection operation.
	MGPickObjects&	unselected_objects	//unselected objects at this selection operation.
		//unselected_objects.size()>=1 only when the already selected objects are selected
		//when add mode is set(or when operation is done with a crtl key pressed).
){
	CZebraDlg& dialog=*getZebraDialog();

	// 選択され直すたびに再描画をする
	if(!dialog.IsWindowVisible()){
		CPoint pt;
		::GetCursorPos(&pt);
		pt.Offset(-4, -4);
		dialog.SetWindowPos(&CWnd::wndTop, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
	}

	// 無条件で再描画開始(消去も含むから)
	m_objectives = current_objects();
	draw_pictures();
	SetStatusMessage(IDS_PROMPT_EXIT);

	// コマンドはここでは終了しない
	return false;
}

void MGEvalSurfZebraTool::draw_pictures(){
	MGColor color =  FromCOLORREF(m_color);
	const mgTLInputParam& tlparam = document()->context()->tessellate_param();
	//const MGPickObjects& objs=current_objects();
	size_t n=m_objectives.size();
	for(size_t i=0; i<n; i++){
		const MGGel* gel=m_objectives[i].top_object();
		erase_temporary(gel,false);
		draw_temporary(new MGEvalZebraGL(gel,
			tlparam, color, m_dThickness, m_bVertical),false,false);
	}
	InvalidateAllStdViews();
}

void MGEvalSurfZebraTool::draw_pictures(COLORREF color, float dThickness, bool bVertical){
	m_color = color;
	m_dThickness = dThickness;
	m_bVertical = bVertical;
	draw_pictures();
}

MGEvalZebraGL::MGEvalZebraGL(
	const MGGel* gel,	///<This must be MGSurface, MGFace, or MGShell(mgAll_2Manifold).
	const mgTLInputParam& tlparam,	///<Tessellation parameter.
	const MGColor& color,	///<zebra color
	float thickness,	///<zebra thickness.
	bool is_vertical	///<direction of the zera stripes.
):mgSysGL(ID_EVAL_SURFACE_ZEBRA, gel),m_tlparam(tlparam)
,m_color(color),m_dThickness(thickness), m_bVertical(is_vertical){
}

mgSysGL* MGEvalZebraGL::clone()const{
	return new MGEvalZebraGL(*this);
}

//Draw this Sysgl.
//This draw is used to draw the pictures for Undo(, Redo) operations.
void MGEvalZebraGL::drawSysGL(){
	const MGFSurface* fsrf=dynamic_cast<const MGFSurface*>(object_id());

	std::vector<mgTL2Triangles> trisVector;   // tessellation 情報
	MGDrawParam dpara(m_tlparam);
	fsrf->triangulate(dpara,MGCL::XYZNormal,trisVector);

	m_color.exec(*this);
	mgGLSLProgram* pGLSL = mgGLSLProgram::getCurrentGLSLProgram();
	pGLSL->setUniform(mgGLSLProgram::ZebraAxis, m_bVertical?mgGLSL::ZebraVert : mgGLSL::ZebraHorizon);
	pGLSL->setUniform(mgGLSLProgram::ZebraSize, m_dThickness);

	drawShade(trisVector,MGCL::WIRE,GL_FILL);
}

void MGEvalZebraGL::draw(MGCL::VIEWMODE viewMode){
	mgFuncTypeSwitcher switcher(mgGLSL::Analysis);//invoke function type Analysis.
	mgSysGL::draw(viewMode);
}

void MGEvalZebraGL::redraw(MGCL::VIEWMODE viewMode){
	mgFuncTypeSwitcher switcher(mgGLSL::Analysis);//invoke function type Analysis.
	GLboolean bEnbaleDepthTest = glIsEnabled(GL_DEPTH_TEST);
	GLint blendMode = glIsEnabled(GL_BLEND);
	mgSysGL::redraw(viewMode);
}

void MGEvalZebraGL::selectionDraw(MGCL::VIEWMODE viewMode){
	// Selection不可
	return;
}

CZebraDlg * MGEvalSurfZebraTool::getZebraDialog(){
	return static_cast<CZebraDlg*>(getModelessDialogPointer());
}