/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/* ***************************************************** */
/********************************************************************/
/**
 * @file fugenView.cpp
 * @brief クラス fugenView の実装
 */
#include "stdafx.h"
#include "fugenView.h"
#include "MainFrm.h"
#include "fugen.h"

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

/////////////////////////////////////////////////////////////////////////////
// fugenView

////// 座標系の描画 //////
void fugenView::updateAxisPictures(float scale){
	const int len = int(scale*COORD_LENGTH);   //coordinate line length.
	const int offset = int(scale*DIST_FROM_CORNER); //offset of origin.
	glm::mat4 modelMatrix, projMatrix;
	int vp[4];
	getModelViewProjectionMatrices(modelMatrix,projMatrix,vp);
	/*std::cout<<"fugenView::updateAxisPictures2::";
	for(int i=0; i<4; i++) for(int j=0; j<4; j++) std::cout<<projMatrix[i][j]<<",";
	std::cout<<std::endl;*/

	int h=int(scale*vp[3]), w=int(scale*vp[2]);
	if(!w || !h){
		return;
	}
	double axislen=diameter()*len/h;

	//MGOpenGLView& glv=glview();
	MGPosition centerW=center(), centerS;
	project(centerW,centerS,&modelMatrix,&projMatrix);

	//Get axis x vector.
	MGPosition xaxisW(centerW), xaxisS; xaxisW(0)+=axislen;
	project(xaxisW,xaxisS,&modelMatrix,&projMatrix);
	xaxisS-=centerS;
	double xlen=xaxisS.len();

	//Get axis y vector.
	MGPosition yaxisW(centerW), yaxisS; yaxisW(1)+=axislen;
	project(yaxisW,yaxisS,&modelMatrix,&projMatrix);
	yaxisS-=centerS;
	double ylen=yaxisS.len();

	//Get axis z vector.
	MGPosition zaxisW(centerW), zaxisS; zaxisW(2)+=axislen;
	project(zaxisW,zaxisS,&modelMatrix,&projMatrix);
	zaxisS-=centerS;
	double zlen=zaxisS.len();

	//Maximum axis length should be len.
	double ratio;
	if(xlen>=ylen){
		if(xlen>=zlen) ratio=xlen;
		else		ratio=zlen;
	}else{
		if(ylen>=zlen) ratio=ylen;
		else		ratio=zlen;
	}
	ratio/=double(len);
	xaxisS/=ratio; yaxisS/=ratio;zaxisS/=ratio;

	int coordinates[7]={
		offset,
		int(xaxisS[0]),int(xaxisS[1]),
		int(yaxisS[0]),int(yaxisS[1]),
		int(zaxisS[0]),int(zaxisS[1])
	};

	m_coordinateDrawer.set_viewport(&vp[0]);	
	if(m_coordinateDrawer.is_made()){
		m_coordinateDrawer.updateCoordinateArrow(coordinates);
	}else{
		m_coordinateDrawer.makeCoordinateArrow(coordinates);
	}

	// このビューがアクティブな場合、座標軸を白く描画する。
	const MGColor* arrowColor;
	if(theApp.current_view() == this)
		arrowColor=&(MGColor::get_instance(MGColor::White));
	else
		arrowColor=&(MGColor::get_instance(MGColor::Black));
	m_coordinateDrawer.setStaticAttribColor(*arrowColor);
	m_coordinateDrawer.set_display();
}

/////////////////////////////////////////////////////////////////////////////
// fugenView クラスのメッセージ ハンドラ

void fugenView::OnInitialUpdate(){
	fugenDoc& doc=*(GetDocument());
	if(doc.get_main_view())
		return;//When already initialized.

	doc.set_main_view(this);

	// Set Window's title.
	CString strTitle;
	strTitle.Format(IDS_FORMAT_VIEW_TITLE_3D,doc.GetTitle());
	GetParent()->SetWindowText(strTitle);

	if(InitOpenGL()){
		const MGContext* ct = document().context();
		importDrawAttribFromContext(*ct);
		importViewAttribFromContext(*ct);
		makeDisplayList();
	} else {
		// OpenGLまわりで初期化に失敗した
		::AfxMessageBox(_T("OpenGLの初期化に失敗しました。\nOpenGLのバージョンを確認してください。"));
		AfxGetMainWnd()->PostMessage(WM_CLOSE, 0, 0);
	}
	doc.updateSnapMode();
}

void fugenView::OnViewVolumePlan(){
	set_perspective(false);
	const MGPlane& pl = cplane().plane();
	ExecChangeCameraSetting(pl.u_deriv(), pl.v_deriv());
}

void fugenView::OnUpdateViewVolumePlan(CCmdUI* pCmdUI){
	// 都合により常に OK とする。
	pCmdUI->Enable();
}

void fugenView::OnViewVolumePerspective(){
	// Import default (perspective) context.
	const MGContext* ct = document().context();
	import_context(*ct);
	Invalidate();
}

void fugenView::OnUpdateViewVolumePerspective(CCmdUI* pCmdUI){
	pCmdUI->Enable(!is_perspective());
	pCmdUI->SetCheck(is_perspective() ? 1 : 0);
}

void fugenView::OnViewVolumeTop(){
	const MGColor* gridC=getUserPrefGridColor();
	MGConstructionPlane& cpl = cplane();
	cpl.set_uaxis_color(gridC[1]);
	cpl.set_vaxis_color(gridC[2]);
	ExecChangeViewport(MGDefault::z_unit_vector(),MGDefault::y_unit_vector());
}

void fugenView::OnUpdateViewVolumeTop(CCmdUI* pCmdUI){
	pCmdUI->Enable(TRUE);
}

void fugenView::OnViewVolumeBottom(){
	const MGColor* gridC=getUserPrefGridColor();
	MGConstructionPlane& cpl = cplane();
	cpl.set_uaxis_color(gridC[1]);
	cpl.set_vaxis_color(gridC[2]);
	ExecChangeViewport(-MGDefault::z_unit_vector(),-MGDefault::y_unit_vector());
}

void fugenView::OnUpdateViewVolumeBottom(CCmdUI* pCmdUI){
	pCmdUI->Enable(TRUE);
}

void fugenView::OnViewVolumeLeft(){
	const MGColor* gridC=getUserPrefGridColor();
	MGConstructionPlane& cpl = cplane();
	cpl.set_uaxis_color(gridC[2]);
	cpl.set_vaxis_color(gridC[3]);
	ExecChangeViewport(-MGDefault::x_unit_vector(),MGDefault::z_unit_vector());
}

void fugenView::OnUpdateViewVolumeLeft(CCmdUI* pCmdUI){
	pCmdUI->Enable(TRUE);
}

void fugenView::OnViewVolumeRight(){
	const MGColor* gridC=getUserPrefGridColor();
	MGConstructionPlane& cpl = cplane();
	cpl.set_uaxis_color(gridC[2]);
	cpl.set_vaxis_color(gridC[3]);
	ExecChangeViewport(MGDefault::x_unit_vector(),MGDefault::z_unit_vector());
}

void fugenView::OnUpdateViewVolumeRight(CCmdUI* pCmdUI){
	pCmdUI->Enable(TRUE);	
}

void fugenView::OnViewVolumeFront(){
	const MGColor* gridC=getUserPrefGridColor();
	MGConstructionPlane& cpl = cplane();
	cpl.set_uaxis_color(gridC[1]);
	cpl.set_vaxis_color(gridC[3]);
	ExecChangeViewport(MGDefault::y_unit_vector(),MGDefault::z_unit_vector());
}

void fugenView::OnUpdateViewVolumeFront(CCmdUI* pCmdUI){
	pCmdUI->Enable(TRUE);
}

void fugenView::OnViewVolumeBack(){
	const MGColor* gridC=getUserPrefGridColor();
	MGConstructionPlane& cpl = cplane();
	cpl.set_uaxis_color(gridC[1]);
	cpl.set_vaxis_color(gridC[3]);
	ExecChangeViewport(-MGDefault::y_unit_vector(),MGDefault::z_unit_vector());
}

void fugenView::OnUpdateViewVolumeBack(CCmdUI* pCmdUI){
	pCmdUI->Enable(TRUE);
}

void fugenView::OnViewCameraCPlaneTop(){
	MGConstructionPlane& cpl = cplane();
	const MGPlane& pl = cpl.plane();
	ExecChangeCameraSetting(pl.u_deriv(), pl.v_deriv());
}

void fugenView::OnUpdateViewCameraCPlaneTop(CCmdUI* pCmdUI){
	pCmdUI->Enable(cplane().enabled());
}

void fugenView::OnViewCameraCPlaneBottom(){
	MGConstructionPlane& cpl = cplane();
	const MGPlane& pl = cpl.plane();
	ExecChangeCameraSetting(pl.u_deriv(), -pl.v_deriv());
}

void fugenView::OnUpdateViewCameraCPlaneBottom(CCmdUI* pCmdUI){
	pCmdUI->Enable(cplane().enabled());
}

void fugenView::OnViewCameraCPlaneLeft(){
	MGConstructionPlane& cpl = cplane();
	const MGPlane& pl = cpl.plane();
	ExecChangeCameraSetting(-pl.v_deriv(), pl.normal());
}

void fugenView::OnUpdateViewCameraCPlaneLeft(CCmdUI* pCmdUI){
	pCmdUI->Enable(cplane().enabled());
}

void fugenView::OnViewCameraCPlaneRight(){
	MGConstructionPlane& cpl = cplane();
	const MGPlane& pl = cpl.plane();
	ExecChangeCameraSetting(pl.v_deriv(), pl.normal());
}

void fugenView::OnUpdateViewCameraCPlaneRight(CCmdUI* pCmdUI){
	pCmdUI->Enable(cplane().enabled());
}

void fugenView::OnViewCameraCPlaneFront(){
	MGConstructionPlane& cpl = cplane();
	const MGPlane& pl = cpl.plane();
	ExecChangeCameraSetting(pl.u_deriv(), pl.normal());
}

void fugenView::OnUpdateViewCameraCPlaneFront(CCmdUI* pCmdUI){
	pCmdUI->Enable(cplane().enabled());
}

void fugenView::OnViewCameraCPlaneBack(){
	MGConstructionPlane& cpl = cplane();
	const MGPlane& pl = cpl.plane();
	ExecChangeCameraSetting(-pl.u_deriv(), pl.normal());
}

void fugenView::OnUpdateViewCameraCPlaneBack(CCmdUI* pCmdUI){
	pCmdUI->Enable(cplane().enabled());
}

void fugenView::OnViewCameraTarget(){
	// Under construction.
//	fugenDoc* pDoc = GetDocument();
//	ASSERT_VALID(pDoc);
//	pDoc->set_current_command_tool(new MGCameraTargetTool(this));
}

void fugenView::OnUpdateViewCameraTarget(CCmdUI* pCmdUI){
//	pCmdUI->Enable(cplane().enabled());
	// Under construction.
	pCmdUI->Enable(FALSE);
}

void fugenView::OnViewCameraCameraAndTarget(){
	// Under construction.
//	fugenDoc* pDoc = GetDocument();
//	ASSERT_VALID(pDoc);
//	pDoc->set_current_command_tool(new MGCameraCameraAndTargetTool(this));
}

void fugenView::OnUpdateViewCameraCameraAndTarget(CCmdUI* pCmdUI){
//	pCmdUI->Enable(cplane().enabled());
	// Under construction.
	pCmdUI->Enable(FALSE);
}

//Get the view title of this view;
CString fugenView::viewTitle()const{
	const fugenDoc& doc=document();
	CString strTitle(doc.GetTitle());
	CString viewName;
	if(is_mainView())
		viewName=_T(" Main View");
	strTitle+=viewName;

	return strTitle;
}
