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

/**
 * @file SurfRevolutionTool.cpp
 * @brief MGSurfRevolutionTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "mg/Straight.h"
#include "mg/RSBRep.h"
#include "mg/Straight.h"
#include "Calc/mgcalc.h"
#include "Calc/surface.h"
#include "fugenView.h"
#include "SurfCmd/SurfRevolutionTool.h"

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

MGSurfRevolutionTool::MGSurfRevolutionTool(fugenDoc* pDoc)
:MGCommandStateOwner(pDoc, ID_SURFACE_REV){
}

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

bool MGSurfRevolutionTool::initiate_tool(){
	MGCommandStateOwner::initiate_tool();
	if(resetCurrentObjects(mgAll_Curve)){
		m_curve = current_objects().front();
		//Input a point.
		set_child_current_command(new MGSurfRevolutionToolIPoint(this));
	}else{
		//select a curve to rotate.
		set_child_current_command(new MGSurfRevolutionToolSCurve(this));
	}
	return false;
}

bool MGSurfRevolutionTool::OnCommandCanceled(UINT nIDS){
	clear_pick_object();
	return MGCommandStateOwner::OnCommandCanceled(nIDS);
}

bool MGSurfRevolutionTool::OnCommandEnd(
	UINT nIDS,
	bool erase_temporary_display
){
	const LInfoVec& linfos=locates();
	if(linfos.size()>=2){
		const MGPosition& P1=linfos[1]->point_world();
		std::unique_ptr<MGSurface> surf(make_model(P1));
		if(surf.get()){
			MGGelPosition gelp(m_curve.bottom_group(),surf.release());
			add_object_to_document(gelp);
			return MGCommandStateOwner::OnCommandEnd(nIDS, erase_temporary_display);
		}
	}
	return OnCommandCanceled(1);
}

std::unique_ptr<MGSurface> MGSurfRevolutionTool::make_model(const MGPosition& pos){
	std::unique_ptr<MGSurface> ret;
	if(m_curve.is_null()){
		return ret;
	}

	const LInfoVec& linfos=locates();
	if(linfos.empty()){
		return ret;
	}

	// m_curve revolution.
	const MGPosition& P0=linfos[0]->point_world();
	MGStraight axis(pos, P0);
	axis.unlimit();

	const MGCurve* c = dynamic_cast<const MGCurve*>(m_curve.top_object());
	std::unique_ptr<MGRSBRep> rsb=MGCL::create_revolved_surface(*c, axis);
	return std::unique_ptr<MGSurface>(rsb.release());
}

void MGSurfRevolutionTool::UpdatePreview(){
	m_spPreview = make_model(cursor());
}

///////////////Surface of revolution curve selection class/////////////
MGSurfRevolutionToolSCurve::MGSurfRevolutionToolSCurve(
	MGCommandStateOwner* owner
):MGSelectState(owner,MGSelectState::SINGLE_SELECT,mgAll_Curve){;}

bool MGSurfRevolutionToolSCurve::initiate_tool(){
	MGSelectState::initiate_tool();
	SetStatusMessage(IDS_PROMPT_CURVE);
	return false;
}

bool MGSurfRevolutionToolSCurve::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).
){
	MGSurfRevolutionTool* owner=state_owner();
	owner->m_curve = objs.front();
	set_sibling_next_command(new MGSurfRevolutionToolIPoint(owner));
	return false;
}

/////////////Point input class//////////////
MGSurfRevolutionToolIPoint::MGSurfRevolutionToolIPoint(MGCommandStateOwner* owner)
:MGLocateState(owner,UNLOCK_SNAP_ATTRIB,LINE_RUBBER,POINTLINE_IPDRAW){
}

bool MGSurfRevolutionToolIPoint::OnLocated(
	const MGLocateInfo& linfo
){
	size_t np=locates().size();
	if(np>=2){
		MGSurfRevolutionTool* pOwner = state_owner();
		return pOwner->OnCommandEnd(1);
	}

	return false;
}

void MGSurfRevolutionToolIPoint::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	MGSurfRevolutionTool* pOwner = state_owner();
	std::unique_ptr<MGSurface>& preview=pOwner->m_spPreview;
	preview = pOwner->make_model(cursor());
	if(!preview.get()){
		return;
	}
	MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
	mgcalc::CreateDrawFunctor(sgl)(preview.get());
}

void MGSurfRevolutionToolIPoint::prompt_message()const{
	size_t np=locates().size();
	UINT nid=np ? IDS_PROMPT_REVOLVE_AXIS_END:IDS_PROMPT_REVOLVE_AXIS_START;
	SetStatusMessage(UINT(nid));
}
