/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
/********************************************************************/
/**
 * @file CurveProjectionTool.cpp
 * @brief MGCurveProjectionTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "fugen.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "CurveCmd/CurveProjectionTool.h"
#include "Calc/mgproject.h"

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

// MGCurveProjectionTool

MGCurveProjectionTool::MGCurveProjectionTool(fugenDoc* pDoc)
	 : MGCommandStateOwner(pDoc, ID_CURVE_PROJECT),
	   m_nIDS(1)
{}

void MGCurveProjectionTool::import_selected(){
	// 選択オブジェクトをすべてチェック
	m_point = select_from_current_objects(mgAll_Point);
	m_curve = select_from_current_objects(mgAll_Curve);
	m_surf  = select_from_current_objects(mgAll_FSurface);
	m_shell = select_from_current_objects(mgAll_Shell);
}

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

bool MGCurveProjectionTool::initiate_tool(){
	MGCommandStateOwner::initiate_tool();
	import_selected();
	if(!m_point.empty() || !m_curve.empty()){
		if(m_surf.empty() && m_shell.empty()){
			set_child_current_command(new MGProjectionSSurf(this));
			return false;
		}else{
			// 計算開始
			m_dir = theApp.currentfugenView(document())->cplane().plane().normal();
			if(!calculate()){
				return OnCommandEnd(m_nIDS);
			}
			return OnCommandEnd(1);
		}
	}else{
		set_child_current_command(new MGProjectionSCurve(this));
	}
	return false;
}

bool MGCurveProjectionTool::calculate(){
	if(m_point.empty() && m_curve.empty()){
		// みなしキャンセル
		return false;
	}
	if(m_surf.empty() && m_shell.empty()){
		// みなしキャンセル
		return false;
	}
	ASSERT(!m_dir.is_null());
	
	// 計算開始
	SetStatusMessage(IDS_PROMPT_COMPUTE);
	CWaitCursor sandglass;
	
	// 1. point, curve を統合
	m_point.push_back(m_curve);
	m_curve.clear();
	
	// 2. surf, shell を統合
	m_surf.push_back(m_shell);
	m_shell.clear();

	// 3. 計算開始
	std::list<std::unique_ptr<MGGel>> res;
	MGPickObjects::iterator first = m_point.begin(), last = m_point.end();
	for(int j=0; first != last; ++first, j++){
		MGPickObjects::iterator first2 = m_surf.begin(), last2 = m_surf.end();
		for(; first2 != last2; ++first2){
			mgcalc::MGProject tmp((*first2)->top_object(), (*first)->top_object(), m_dir);
			if(tmp.calculate()){
				res.splice(res.end(), std::move(tmp.result()));
				//tmp.release();
			}
		}
	}
	if(res.empty()){
		// failed
		m_nIDS = IDS_FAIL_PROJECT;
		return false;
	}
	// ドキュメントを変更
	addListGelsToCurrentGroup(std::move(res));
	return true;
}

// MGProjectionSCurve
MGProjectionSCurve::MGProjectionSCurve(MGCommandStateOwner* owner)
:MGSelectState(
	 owner,
	 MGSelectState::MULTIPLE_SELECT,
	 mgAll_Curve// | mgAll_Point
 ){
	// 見栄えが悪いがやむを得ない
	abstract_gels().push_back(mgAll_Point);
}

bool MGProjectionSCurve::initiate_tool(){
	MGSelectState::initiate_tool();

	//clear_pick_object();
	MGCurveProjectionTool* owner = state_owner();
	if(!owner->m_surf.empty() || !owner->m_shell.empty()){
		MGPickObjects cobjs(owner->m_surf);
		cobjs.push_back(owner->m_shell);
		set_current_object(cobjs);
	}
	set_add_mode();
	lock_so_far();
	SetStatusMessage(IDS_PROMPT_PROJECT_1);
	return false;
}

bool MGProjectionSCurve::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	switch(nChar){
	case VK_RETURN:{
			MGCurveProjectionTool* owner = state_owner();
			owner->import_selected();
			if(!owner->m_surf.empty() || !owner->m_shell.empty()){
				owner->m_dir = pView->cplane().plane().normal();
				if(!owner->calculate()){
					owner->OnCommandEnd(owner->m_nIDS);
				}
				return owner->OnCommandEnd(1);
			}else{
				set_sibling_next_command(new MGProjectionSSurf(owner));
				return false;
			}
		}
	default:
		return MGSelectState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
	}
}

// MGProjectionSSurf

MGProjectionSSurf::MGProjectionSSurf(MGCommandStateOwner* owner)
	 : MGSelectState(
		 owner,
		 MGSelectState::MULTIPLE_SELECT,
		 mgAll_2Manifold)
{}

bool MGProjectionSSurf::initiate_tool(){
	MGSelectState::initiate_tool();
	set_add_mode();
	lock_so_far();
	SetStatusMessage(IDS_PROMPT_PROJECT_2);
	return false;
}

bool MGProjectionSSurf::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	switch(nChar){
	case VK_RETURN:{
			MGCurveProjectionTool* owner = state_owner();
			owner->import_selected();	
			if(!owner->m_point.empty() || !owner->m_curve.empty()){
				owner->m_dir = pView->cplane().plane().normal();
				if(!owner->calculate()){
					owner->OnCommandEnd(owner->m_nIDS);
				}
				return owner->OnCommandEnd(1);
			}else{
				set_sibling_next_command(new MGProjectionSCurve(owner));
				return false;
			}
		}
	default:
		return MGSelectState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
	}
}
