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

/**
 * @file SurfGridPointsTool.cpp
 * @brief MGSurfGridPointsTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "fugen.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "mg/SBRep.h"
#include "GLSurfGridPointsDlg.h"
#include "SurfCmd/SurfGridPointsTool.h"
#include "Misc/UserPreference.h"

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

// MGSurfGridPointsTool

MGSurfGridPointsTool::MGSurfGridPointsTool(fugenDoc* pDoc)
	 : MGLocateState(
		 pDoc,
		 ID_SURFACE_FROM_GRID_POINTS,
		 NO_RUBBER,
		 POINT_IPDRAW),
	   m_nu(2),
	   m_nv(2)
{
}

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

bool MGSurfGridPointsTool::initiate_tool(){
	MGLocateState::initiate_tool();
	const UserPreference& pref = UserPreference::getInstance();
	m_nu = pref.GetIntValue(upv_Surface_GridPoints_U);
	m_nv = pref.GetIntValue(upv_Surface_GridPoints_V);

	// 最初のメッセージ
	SetStatusMessage(IDS_PROMPT_CPOINT_NUM);
	if(!input_param()){
		// cancel
		return OnCommandEnd(3);
	}
	SetStatusMessage(IDS_PROMPT_SURFACE_CPOINT, 0, 0);
	return false;
}

bool MGSurfGridPointsTool::terminate_tool(bool cancel)
{
	UserPreference& pref = UserPreference::getInstance();
	pref.SetIntValue(upv_Surface_GridPoints_U, m_nu);
	pref.SetIntValue(upv_Surface_GridPoints_V, m_nv);

	return MGLocateState::terminate_tool(cancel);
}

bool MGSurfGridPointsTool::input_param(){
	// 専用のダイアログボックスを作らないといけない
	CGLSurfGridPointsDlg dlg;
	dlg.m_nu = m_nu;
	dlg.m_nv = m_nv;
	if(IDOK != dlg.DoModal()){
		return false;
	}
	
	m_nu = dlg.m_nu;
	m_nv = dlg.m_nv;
	if(m_nu <= 1 || m_nv <= 1){
		return false;
	}

	m_total = m_nu * m_nv;
	return true;
}

bool MGSurfGridPointsTool::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
){
	const LInfoVec& linfos=locates();
	size_t n=linfos.size();
	if(n != m_total){
		// みなしキャンセル
		return MGLocateState::OnCommandEnd(3);
	}

	SetStatusMessage(IDS_PROMPT_COMPUTE);
	CWaitCursor sandglass;

	// convert vector<MGPosition> to MGSPointSeq.
	MGSPointSeq sp(m_nu, m_nv, 3);
	for(int j = 0; j < m_nv; j++){
		for(int i = 0; i < m_nu; i++){
			sp.store_at(i, j, linfos[i+j*m_nu]->point_world());
		}
	}

	int order_u = 4, order_v = 4;
	if(m_nu < order_u) order_u = m_nu;
	if(m_nv < order_v) order_v = m_nv;

	std::unique_ptr<MGSBRep> surf(new MGSBRep);
	surf->buildByInterpolation(sp, order_u, order_v);
	add_object_to_current_group(surf.release());
	return MGLocateState::OnCommandEnd(1);
}

bool MGSurfGridPointsTool::OnLocated(const MGLocateInfo& info){
	int n = (int)locates().size();
	if(n < m_total){
		SetStatusMessage(IDS_PROMPT_SURFACE_CPOINT, n%m_nu, n/m_nu);
		return false;
	}

	return OnCommandEnd(1);
}
