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

// fugenStatusBar.cpp : インプリメンテーション ファイル

#include "stdafx.h"
#include "Misc/UserPreference.h"
#include "fugen.h"
#include "fugenDoc.h"
#include "Common/CommandBase.h"
#include "fugenStatusBar.h"

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

/////////////////////////////////////////////////////////////////////////////
// fugenStatusBar
//The design of the Status bar is as:
// (*COMMAND_MSG,*COORD,*GRID,*ANGLE,ID_SEPARATOR).
// COMMAND_MSG: Dispays current command, and the message from the command,
//        which is handled by MGCommandBase::SetStatusMessage().
// COORD: Displays located 3D(2D) coordinates, which is handled
//        by fugenView::display_position_in_status_bar().
// GRID and ANGLE: are treated as buttons to change the status, to turn on/off
//        their mode. In ANGLE pane, ELEVATE or TAB are also displayed when
//        the mode is designated in MGLocate's sub class to input in the mode.
//        GRID's status is controled by the document(m_document), an ANGLE
//        is by the current command(subclass of MGLocate).

namespace{
	const COLORREF colrOn = RGB(0, 0, 250);//Color of the restriction enabled.
	const COLORREF colrOff= GetSysColor(COLOR_GRAYTEXT);
					//Color of a doc is imported and the restriction disabled.

	const COLORREF colrNoUpd = RGB(255, 0, 0);//Color of no update.
}

BEGIN_MESSAGE_MAP(fugenStatusBar, CStatusBar)
	//{{AFX_MSG_MAP(fugenStatusBar)
	ON_WM_LBUTTONDOWN()
	ON_WM_SIZE()
	ON_WM_MOUSEMOVE()
	ON_WM_CREATE()

	ON_MESSAGE(WM_GL_STATUSBAR, OnStatusMsg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

fugenStatusBar::fugenStatusBar()
: m_document(0){
	UserPreference& pref = UserPreference::getInstance();
	pref.exportToCRestrict(m_restriction);//Initialize status bar's cursor restriction.
}

fugenStatusBar::~fugenStatusBar(){
}

BOOL fugenStatusBar::DestroyWindow(){
	//Save cursor restriction mode data.
	UserPreference& pref = UserPreference::getInstance();
	pref.importFromCRestrict(m_restriction);

	return CControlBar::DestroyWindow();
}

void fugenStatusBar::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){
	CRect rc(lpDrawItemStruct->rcItem);
	CDC dc;
	VERIFY(dc.Attach(lpDrawItemStruct->hDC));

	rc.OffsetRect(1, 1);	
	dc.SetBkMode(TRANSPARENT);
	CString str;
	UINT nID = GetItemID(lpDrawItemStruct->itemID);
	COLORREF color=colrOn;

	switch(nID){
	case IDS_INDICATOR_GRID:
		if(!isGridEnabled())
			color = colrOff;
		break;

	case IDS_INDICATOR_ANGLE:
		//Define letters on Angle pane.
		if(m_restriction.mode()==MGCursorRestriction::ELEVATION){
			nID=IDS_INDICATOR_ELEVATE;
		}else if(m_restriction.mode()==MGCursorRestriction::TABMODE){
			nID=IDS_INDICATOR_TAB;
		}

		//Define the color.
		if(m_restriction.isAETUpdateProhibitted() &&
			(m_restriction.isMapToStraightMode() || m_restriction.isAngleMode()))
			color=colrNoUpd;
		else if(m_restriction.mode()==MGCursorRestriction::FREE ||
			m_restriction.mode()==MGCursorRestriction::PLANAR){
			//When m_restriction=FREE, ANGLE, or ANGLE_PLANAR, display is ANGLE.
			color = colrOff;
		}
		break;

	case IDS_INDICATOR_PLANAR:
		//This pane's letters are always PLANAR.

		//Define color.
		color=colrOff;
		if(m_restriction.isPlanarMode()){
			if(m_restriction.isPUpdateProhibitted()){
				color = colrNoUpd;
			}else if(m_restriction.isPlanarMode())
				color = colrOn;
		}
		break;
	}

	dc.SetTextColor(color);
	str.LoadString(nID);
	if(nID==IDS_INDICATOR_ANGLE && m_restriction.isAngleMode()){
		CString degStr; degStr.Format(_T("%5.1f"),m_restriction.get_angle());
		str.Append(degStr);
	}
	dc.DrawText(str, str.GetLength(), &rc, DT_LEFT | DT_BOTTOM);
	dc.Detach();
}

BOOL fugenStatusBar::PreTranslateMessage(MSG* pMsg){
	m_tip.RelayEvent(pMsg);
	return CStatusBar::PreTranslateMessage(pMsg);
}

void fugenStatusBar::SetDocument(fugenDoc* doc){
	if(doc!=m_document){
		m_document = doc;
		updateDisplay();
	}
}

void fugenStatusBar::DisplayCommandMessage(LPCTSTR lpszCmdMessage){
	SetPaneText(CommandToIndex(ID_INDICATOR_COMMAND_MSG), lpszCmdMessage);
}

void fugenStatusBar::DisplayCoord(double u, double v){
	CString str;
	str.Format(IDS_FORMAT_COORD_2D, 'u', u, 'v', v);
	DisplayCoord(str);
}

void fugenStatusBar::DisplayCoord(double x, double y, double z){
	CString str;
	str.Format(IDS_FORMAT_COORD_3D, x, y, z), 
	DisplayCoord(str);
}

void fugenStatusBar::DisplayCoord(const CString& str){
	SetPaneText(CommandToIndex(ID_INDICATOR_COORD), str);
}

void fugenStatusBar::UpdateTipText(){
	UINT nIDTextGrid = IDS_TOOLTIP_GRID_NORMAL;
	UINT nIDTextAngle = IDS_INDICATOR_ANGLE_NORMAL;//message:angle mode is disabled.
	UINT nIDTextPlanar = IDS_INDICATOR_PLANAR_NORMAL;//message:planar mode is disabled.
	if(m_document){
		const MGSnapAttrib& snp = m_document->getSnapAttr();
		nIDTextGrid =
			snp.getGrid() ? IDS_TOOLTIP_GRID_ON : IDS_TOOLTIP_GRID_OFF;

		if(m_restriction.isAETUpdateProhibitted())
			nIDTextAngle=IDS_STRING_MODE_NOUPDT;//message:cannot update
		else
		switch(m_restriction.mode()){
			case MGCursorRestriction::FREE:
			case MGCursorRestriction::PLANAR:
				nIDTextAngle =IDS_INDICATOR_ANGLE_OFF;//message when off:can turn on angle.
				break;
			default:
				nIDTextAngle =IDS_INDICATOR_ANGLE_ON;//message when on:can turn off restriction.
		}

		if(m_restriction.isPUpdateProhibitted())
			nIDTextPlanar=IDS_STRING_MODE_NOUPDT;//message:cannot update
		else
		switch(m_restriction.mode()){
			case MGCursorRestriction::PLANAR:
			case MGCursorRestriction::ANGLE_PLANAR:
				nIDTextPlanar=IDS_INDICATOR_PLANAR_ON;//message when on:can turn off planar
				break;
			default:
				nIDTextPlanar=IDS_INDICATOR_PLANAR_OFF;//message when off:can turn on planar
		}
		
	}
	
	int nIDTipGrid = CommandToIndex(IDS_INDICATOR_GRID);
	int nIDTipAngle = CommandToIndex(IDS_INDICATOR_ANGLE);
	int nIDTipPlanar = CommandToIndex(IDS_INDICATOR_PLANAR);

	m_tip.UpdateTipText(nIDTextGrid, this, nIDTipGrid);
	m_tip.UpdateTipText(nIDTextAngle, this, nIDTipAngle);
	m_tip.UpdateTipText(nIDTextPlanar, this, nIDTipPlanar);
}

//Get the MGCursorRestriction mode.
void fugenStatusBar::GetRestrictionModeAngle(
	MGCursorRestriction::CURSOR_RESTRICTION_MODE& mode,
	double& angle	//effective only when mode=ANGLE, and input the angle in degree.
){
	mode=m_restriction.mode();
	angle=m_restriction.get_angle();
}

//Test if grid mode is enabled.
bool fugenStatusBar::isGridEnabled(){
	if(m_document){
		const MGSnapAttrib& snp = m_document->getSnapAttr();
		return snp.getGrid();
	}else
		return false;
}

/////////////////////////////////////////////////////////////////////////////
// fugenStatusBar メッセージ ハンドラ

int fugenStatusBar::OnCreate(LPCREATESTRUCT lpCreateStruct) {
	if (CStatusBar::OnCreate(lpCreateStruct) == -1)
		return -1;

	return 0;
}

LRESULT fugenStatusBar::OnStatusMsg(WPARAM wParam, LPARAM lParam){
	LPCTSTR lpszText = reinterpret_cast<LPCTSTR>(lParam);
	SetPaneText(CommandToIndex(ID_INDICATOR_COMMAND_MSG), lpszText);
	return TRUE;
}

void fugenStatusBar::SetupToolTips(){
	const int nIDTipGrid = CommandToIndex(IDS_INDICATOR_GRID);
	const int nIDTipAngle = CommandToIndex(IDS_INDICATOR_ANGLE);
	const int nIDTipPlanar = CommandToIndex(IDS_INDICATOR_PLANAR);

	CRect rc; // Dummy rectangle
	if(!m_tip.Create(this)
	   || !m_tip.AddTool(this, _T(""), rc, nIDTipGrid)
	   || !m_tip.AddTool(this, _T(""), rc, nIDTipAngle)
	   || !m_tip.AddTool(this, _T(""), rc, nIDTipPlanar)
	   ){
		TRACE("Failed to add tooltips in fugenStatusBar\n");
		return;
	}

	EnableToolTips(TRUE);
	m_tip.Activate(TRUE);
	UpdateTipText();
}

void fugenStatusBar::OnLButtonDown(UINT nFlags, CPoint point){
	CStatusBar::OnLButtonDown(nFlags, point);
	if(!m_document)
		return;

	TOOLINFO ti;
	if(m_tip.HitTest(this, point, &ti)){
		UINT nID = GetItemID((UINT)ti.uId);
		MGSnapAttrib& sa = m_document->getSnapAttr();
		
		switch(nID){
		case IDS_INDICATOR_GRID:
			m_document->enableGridSnap(!sa.getGrid());
			break;
		case IDS_INDICATOR_ANGLE:
			if(!m_restriction.isAETUpdateProhibitted()){
				if(m_restriction.isAngleMode())//angle or angle&planar
					m_restriction.freeAngleMode();
				else if(m_restriction.isMapToStraightMode())//elevate or tab
					m_restriction.SetRestrictionMode(MGCursorRestriction::FREE);
				else//free or planar
					m_restriction.addAngleMode();
			}
			break;
		case IDS_INDICATOR_PLANAR:
			if(!m_restriction.isPUpdateProhibitted()){
				if(m_restriction.isPlanarMode())
					m_restriction.freePlanarMode();
				else
					m_restriction.addPlanarToPreviousMode();
			}
			break;
		}
		updateDisplay();
	}
}

void fugenStatusBar::OnSize(UINT nType, int cx, int cy){
	CStatusBar::OnSize(nType, cx, cy);

	// ツールチップの反応する区画矩形を設定する

	const UINT panes[] = {
		IDS_INDICATOR_GRID,
		IDS_INDICATOR_ANGLE,
		IDS_INDICATOR_PLANAR
	};
	const int nPane = sizeof(panes)/sizeof(UINT);

	for(int i = 0; i < nPane; ++i){
		int nIndex = CommandToIndex(panes[i]);
		if(nIndex != -1){
			CRect rc;
			GetItemRect(nIndex, rc);
			m_tip.SetToolRect(this, nIndex, rc);
		}
	}
}

//Update the display of this bar's ANGLE/ELEBATION/TAB mode display
//fromth current m_restriction status.
void fugenStatusBar::updateDisplay(){
	UpdateTipText();
	Invalidate();
}
