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

/**
 * @file RectVertTool.cpp
 * @brief MGRectVertTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "mg/LBRep.h"
#include "topo/Face.h"
#include "Calc/surface.h"
#include "Calc/curve.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "SurfCmd/RectVertTool.h"

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

// MGRectVertToolBase

MGRectVertToolBase::MGRectVertToolBase(fugenDoc* pDoc, int nCmdID)
: MGLocateState(pDoc, nCmdID, NO_RUBBER, POINT_IPDRAW){
}

void MGRectVertToolBase::do_make_temporary_display(mgSysGL& sgl,fugenView*){
	const LInfoVec& linfos=locates();
	size_t n=linfos.size();
	if(n == 2){
		const MGPosition& A = linfos[0]->point_world();
		const MGPosition& B = linfos[1]->point_world();
		const MGPosition& P = cursor();
		if(B == P || A == P) return;

		MGPosition corners[4];
		buildRectPointsFrom3Points(A,B,P,corners);

		MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
		sgl.drawPolyline(4,corners,true);
	}
}

bool MGRectVertToolBase::OnLocated(const MGLocateInfo& info){
	const LInfoVec& linfos=locates();
	switch(linfos.size()){
	case 1:{
		//Elevation restriction conditions are determined by the 1st point.
		disable_AETPmode();
		setDrawerRubber(LINE_RUBBER);
		}
		break;
	case 2:{
		MGLocateInfo& linf0=*linfos[0];
		const MGPosition& P0=linf0.point_world();
		const MGPosition& P1=linfos[1]->point_world();
		MGPosition Pmid=(P0+P1)*.5;
		const MGVector& normal=linf0.window()->cplane().plane().normal();
		setElevationRestrictionToProhibitUpdate(Pmid, normal);
		setDrawerRubber(NO_RUBBER);
		}
		break;
	case 3:{
		const MGPosition& P0 = linfos[0]->point_world();
		const MGPosition& P2 = linfos[2]->point_world();
		if(P0 == P2){
			cancel_last_locate();
			break;
		}
		make_model();
		disable_AETPmode();
		return OnCommandEnd(1); // コマンド終了
		}
	}

	return false;
}

void MGRectVertToolBase::prompt_message()const{
	UINT nid=0;
	switch(locates().size()){
	case 0:
		nid=IDS_PROMPT_RECT_EDGE_START;
		break;
	case 1:
		nid=IDS_PROMPT_RECT_EDGE_END;
		break;
	case 2:
		nid=IDS_PROMPT_RECT_HEIGHT;
		break;
	}
	SetStatusMessage(nid);
}

// class MGRectFaceVertTool
MGRectFaceVertTool::MGRectFaceVertTool(fugenDoc* pDoc)
: MGRectVertToolBase(pDoc, ID_SURFACE_RECT_VERT){
}

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

void MGRectFaceVertTool::make_model(){
	const LInfoVec& linfos=locates();
	assert(linfos.size()>=3);

	const MGPosition& A = linfos[0]->point_world();
	const MGPosition& B = linfos[1]->point_world();
	const MGPosition& P = linfos[2]->point_world();

	MGPosition corners[4];
	buildRectPointsFrom3Points(A,B,P,corners);

	std::unique_ptr<MGFace> rect = mgcalc::rectangular_face(corners);
	add_object_to_current_group(rect.release());
}

// class MGPlaneVertTool

MGPlaneVertTool::MGPlaneVertTool(fugenDoc* pDoc)
:MGRectVertToolBase(pDoc, ID_SURFACE_PLANE_VERT){
}

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

void MGPlaneVertTool::make_model(){
	const LInfoVec& linfos=locates();
	assert(linfos.size()>=3);

	const MGPosition& A = linfos[0]->point_world();
	const MGPosition& B = linfos[1]->point_world();
	const MGPosition& P = linfos[2]->point_world();

	MGPosition corners[4];
	buildRectPointsFrom3Points(A,B,P,corners);

	MGUnit_vector U(B-A),V,W;
	const MGPosition& C=corners[2];
	U.orthonormal(C-B,V,W);
	add_object_to_current_group(new MGPlane(U,V,(A+C)*.5));
}
