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

/**
 * @file SplineSketchTool.cpp
 * @brief MGSplineSketchTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "mg/LBRep.h"
#include "mg/LBRepEndC.h"
#include "Calc/mgcalc.h"
#include "Calc/curve.h"
#include "fugen.h"
#include "fugenView.h"
#include "Common/CommandStateOwner.h"
#include "Misc/UserPreference.h"
#include "CurveCmd/SplineSketchTool.h"

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

// MGSplineSketchTool

MGSplineSketchTool::MGSplineSketchTool(fugenDoc* pDoc)
: MGLocateState(pDoc,ID_CURVE_SPLINE_SKETCH,NO_RUBBER,POINT_IPDRAW),
m_bClose(false), m_ButtonDown(false){
}

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

bool MGSplineSketchTool::initiate_tool(){
	MGLocateState::initiate_tool();
	const UserPreference& pref = UserPreference::getInstance();
	m_bClose = pref.GetBoolValue(upv_Curve_SplineSketch_Close);
	//m_bPlanar = pref.GetBoolValue(upv_Curve_SplineSketch_Planar);
	return false;
}

bool MGSplineSketchTool::terminate_tool(bool cancel){
	UserPreference& pref = UserPreference::getInstance();
	pref.SetBoolValue(upv_Curve_SplineSketch_Close, m_bClose);
	//pref.SetBoolValue(upv_Curve_SplineSketch_Planar, m_bPlanar);

	return MGLocateState::terminate_tool(cancel);
}

namespace{
	double accumulatedLength;
	const double MINIMUM_LEN=1.0;
}

void MGSplineSketchTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	if(m_ButtonDown)
		addPointMakeSpline(cursor(),m_ButtonDown);
	if(m_current.get()){
		MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
		m_current->drawWire(sgl);
	}
	if(!m_tmp.empty()){
		MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
		std::for_each(m_tmp.begin(), m_tmp.end(), mgcalc::CreateDrawFunctor(sgl));
	}
}

bool MGSplineSketchTool::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	switch(nChar){
	case VK_BACK:
		return false;//We do not accept backspace, neglect it.
	case VK_RETURN:
		// 計算して終了
		if(m_tmp.empty()){
			// 単なるキャンセル
			return OnCommandEnd(3);
		}
	
		// ドキュメントを変更
		addUniqueGelsToCurrentGroup(m_tmp.begin(), m_tmp.end());
		return OnCommandEnd(1);
	case 'c':
	case 'C':
		// 閉じる
		if(!m_ButtonDown){
			m_bClose = !m_bClose;
			prompt_message();
		}
		return false;
	default:
		return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
	}
}

bool MGSplineSketchTool::OnLocated(const MGLocateInfo& info){
	m_ButtonDown = true;
	m_pos.clear();
	m_pos.push_back(info.point_world());
	return false;
}

bool MGSplineSketchTool::OnLButtonUp(fugenView* pView, CPoint, UINT, CPoint){
	m_ButtonDown = false;
	addPointMakeSpline(cursor(),m_ButtonDown);
	if(m_current.get()){
		m_tmp.emplace_back(m_current.release());
	}

	m_pos.clear();
	draw_temporary();
	prompt_message();
	return false;
}

void MGSplineSketchTool::prompt_message() const{
	if(m_ButtonDown){
		// 終了するにはボタンを離します...
		SetStatusMessage(IDS_PROMPT_SKETCH);
	}else{
		// ドラッグで描画...
		CString str1;
		str1.LoadString(m_bClose ? IDS_YES : IDS_NO);
		SetStatusMessage(IDS_PROMPT_SKETCH_IDLE, str1);
	}
}

void MGSplineSketchTool::addPointMakeSpline(const MGPosition& point, bool ButtonDown){
	MGPosition& lastP=m_pos.back();
	double len=lastP.distance(point);
	accumulatedLength+=len;

	if(len>=MINIMUM_LEN){
		m_pos.push_back(point);
	}else{
		if(!ButtonDown)
			lastP=point;
	}

	// スプラインを生成してみる
	if(m_pos.size() >= 3){
		std::vector<MGPosition> posTemp(m_pos);
		if(m_bClose){
			posTemp.push_back(m_pos[0]);
		}
		MGLBRep* lb=new MGLBRep;
		lb->buildByInterpolation(posTemp, 4, m_bClose);
		lb->remove_knot(); // remove knots MORE roughly
		m_current.reset(lb);
	}
}
