/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
/**
 * @file fugenDoc5.cpp
 * @brief fugenDoc.h の実装。編集系メニューハンドラーが中心。
 */
#include "stdafx.h"

#include "mg/Point.h"
#include "mg/PickObject.h"
#include "mg/GelPositions.h"
#include "topo/Shell.h"
#include "fugen.h"
#include "fugenDoc.h"

#include "IO/GLFileManager.h"
#include "IO/GLFileImporter.h"

#include "Common/CommandStateOwner.h"
#include "Undo/GelAddAction.h"
#include "Undo/GelRemoveAction.h"
#include "Undo/IActionManager.h"

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

namespace docSelect{
	auto isShown = [](const MGObject* obj) {return !obj->no_display(); };
	auto isPoint = [](const MGObject* obj) {
		return dynamic_cast<const MGPoint*>(obj) && !obj->no_display(); };
	auto isCurve = [](const MGObject* obj) {
		return dynamic_cast<const MGCurve*>(obj) && !obj->no_display(); };
	auto isFSurface = [](const MGObject* obj) {
		return dynamic_cast<const MGFSurface*>(obj) && !obj->no_display(); };
	auto isShell = [](const MGObject* obj) {
		return dynamic_cast<const MGShell*>(obj) && !obj->no_display(); };
	auto isMesh = [](const MGObject* obj) {return obj->type_is(mgAll_STL) && !obj->no_display(); };
}

void fugenDoc::OnEditUndo(){
	m_undoManager->Undo();
	SetStatusMessage(IDS_PROMPT_UNDO_FINISH);
}

void fugenDoc::OnUpdateEditUndo(CCmdUI* pCmdUI){
	pCmdUI->Enable(m_undoManager->CanUndo()
		&& !current_command_tool()->is_locked());
}

void fugenDoc::OnEditRedo(){
	m_undoManager->Redo();
	SetStatusMessage(IDS_PROMPT_REDO_FINISH);
}

void fugenDoc::OnUpdateEditRedo(CCmdUI* pCmdUI){
	pCmdUI->Enable(m_undoManager->CanRedo()
		&& !current_command_tool()->is_locked());
}

void fugenDoc::OnEditCopy(){
}

void fugenDoc::OnUpdateEditCopy(CCmdUI* pCmdUI){
//	pCmdUI->Enable(!m_current_objects.empty());
	pCmdUI->Enable(FALSE);
}

void fugenDoc::OnEditCut(){
}

void fugenDoc::OnUpdateEditCut(CCmdUI* pCmdUI){
//	pCmdUI->Enable(!m_current_objects.empty()
//		&& !current_command_tool()->is_locked());
	pCmdUI->Enable(FALSE);
}

void fugenDoc::OnEditPaste(){
}

void fugenDoc::OnUpdateEditPaste(CCmdUI* pCmdUI){
//	pCmdUI->Enable(!current_command_tool()->is_locked());
	pCmdUI->Enable(FALSE);
}

void fugenDoc::OnEditClear(){
	ASSERT(!current_command_tool()->is_locked());
	ASSERT(!m_current_objects.empty());

	MGGelPositions gelps(m_current_objects);
	(new CGelRemoveAction(this,gelps))->Do();
}

void fugenDoc::OnUpdateEditClear(CCmdUI* pCmdUI){
	pCmdUI->Enable(!current_command_tool()->is_locked() 
		&& !m_current_objects.empty());
}


void fugenDoc::OnSelectAll(){
	MGGelPositions gelps;
	gelps.append_if(&m_group, m_group.begin(), m_group.end(), docSelect::isShown);
	set_current_object(gelps);
}

void fugenDoc::OnUpdateSelectAll(CCmdUI* pCmdUI){
	pCmdUI->Enable(!m_group.empty()
		&& !current_command_tool()->is_locked());
}

namespace{
	struct GelRel{
		bool operator()(MGGelPosition& lhs, MGGelPosition& rhs) const{
			return lhs.top_object() < rhs.top_object();
		}
	};
}
void fugenDoc::OnSelectInvert(){
	MGGelPositions picked(current_objects());

	MGGelPositions shown;
	shown.append_if(&m_group, m_group.begin(), m_group.end(), docSelect::isShown);

	std::sort(picked.begin(), picked.end(), GelRel());
	std::sort(shown.begin(), shown.end(), GelRel());

	MGGelPositions result;
	result.reserve(abs(int(shown.size() - picked.size())));
	std::set_symmetric_difference(
		picked.begin(), picked.end(), 
		shown.begin(), shown.end(),
		std::back_inserter(result), GelRel()
	);
	set_current_object(result);
}

void fugenDoc::OnUpdateSelectInvert(CCmdUI* pCmdUI){
	pCmdUI->Enable(!current_objects().empty());
}

void fugenDoc::OnSelectClear(){
	set_current_object();
}

void fugenDoc::OnUpdateSelectClear(CCmdUI* pCmdUI){
	pCmdUI->Enable(!m_current_objects.empty()
		&& !current_command_tool()->is_locked());
}

void fugenDoc::OnSelectLast(){
	MGGelPositions& gelps = m_last_added;
	if(gelps.empty()) return;

	MGGroup* tmp = 0;
	MGGelPositions result;
	MGGelPositions::iterator first = gelps.begin(), last = gelps.end();
	for(; first != last; ++first){
		m_group.find(first->top_object(), tmp);
		if(tmp){
			result.push_back(*first);
		}
	}
	set_current_object(result);
}

void fugenDoc::OnUpdateSelectLast(CCmdUI* pCmdUI){
	pCmdUI->Enable(!m_last_added.empty() 
		&& !current_command_tool()->is_locked());
}

void fugenDoc::OnSelectCurve(){
	MGGelPositions gelps;
	gelps.append_if(&m_group, m_group.begin(), m_group.end(), docSelect::isCurve);
	set_current_object(gelps);
}

void fugenDoc::OnUpdateSelectCurve(CCmdUI* pCmdUI){
	pCmdUI->Enable(!m_group.empty()
		&& !current_command_tool()->is_locked());
}

void fugenDoc::OnSelectPoint(){
	MGGelPositions gelps;
	gelps.append_if(&m_group, m_group.begin(), m_group.end(), docSelect::isPoint);
	set_current_object(gelps);
}

void fugenDoc::OnUpdateSelectPoint(CCmdUI* pCmdUI){
	pCmdUI->Enable(!m_group.empty()
		&& !current_command_tool()->is_locked());
}

void fugenDoc::OnSelectSurface(){
	MGGelPositions gelps;
	gelps.append_if(&m_group, m_group.begin(), m_group.end(), docSelect::isFSurface);
	set_current_object(gelps);
}

void fugenDoc::OnUpdateSelectSurface(CCmdUI* pCmdUI){
	pCmdUI->Enable(!m_group.empty()
		&& !current_command_tool()->is_locked());
}

void fugenDoc::OnSelectShell(){
	MGGelPositions gelps;
	gelps.append_if(&m_group, m_group.begin(), m_group.end(), docSelect::isShell);
	set_current_object(gelps);
}

void fugenDoc::OnUpdateSelectShell(CCmdUI* pCmdUI){
	pCmdUI->Enable(!m_group.empty()
		&& !current_command_tool()->is_locked());
}

void fugenDoc::OnSelectMesh(){
	MGGelPositions gelps;
	gelps.append_if(&m_group, m_group.begin(), m_group.end(), docSelect::isMesh);
	set_current_object(gelps);
}

void fugenDoc::OnUpdateSelectMesh(CCmdUI* pCmdUI){
	pCmdUI->Enable(!m_group.empty()
		&& !current_command_tool()->is_locked());
}

void fugenDoc::OnF8Key(){
	MGCommandBase* command = current_command_tool();
	MGCommandStateOwner* owner_command = dynamic_cast<MGCommandStateOwner*> (command);
	command = (owner_command) ? owner_command->GetCurState() : command;

	if(command->canF8Key())
		if(command->ProcessF8Key())
			terminate_current_command_tool();
}
void fugenDoc::OnUpdateF8(CCmdUI *pCmdUI){
	pCmdUI->Enable(TRUE);
}

void fugenDoc::OnEscapeKey(){
	MGCommandBase* command = current_command_tool();
	MGCommandStateOwner* owner_command = dynamic_cast<MGCommandStateOwner*> (command);
	command = (owner_command && owner_command->GetCurState())
			  ? owner_command->GetCurState() : command;
	
	command->OnCommandCanceled(1);
	terminate_current_command_tool();

}
void fugenDoc::OnUpdateEscape(CCmdUI *pCmdUI){
	pCmdUI->Enable(TRUE);
}