// GameView.cpp : implementation file
//

#include "stdafx.h"
#include "MW4GameEd2.h"
#include "GameView.h"
#include "ObjectManager.h"
#include "CameraController.h"
#include "Refresher.h"
#include <MFCPlatform\MFCPlatform.hpp>
#include <Stuff\Stuff.hpp>

using namespace Stuff;


/////////////////////////////////////////////////////////////////////////////
// CGameView


CGameView::CGameView(ObjectManager *objman,CWnd *parent)
: m_ZoomYawOrigin(GetInvalidStartPoint())
, m_PitchYawOrigin(GetInvalidStartPoint())
{
	ObjMan=objman;
	DisplayOff=false;
	InLogic=false;
	BadEngine=false;
	
	//	ShowWindow(SW_SHOW);	
	
}

CGameView::~CGameView()
{
}


BEGIN_MESSAGE_MAP(CGameView, CWnd)
//{{AFX_MSG_MAP(CGameView)
ON_WM_PAINT()
ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
ON_WM_SETFOCUS()
ON_WM_CLOSE()
ON_WM_MOUSEMOVE()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGameView message handlers
extern bool gActive;
extern bool gGotFocus;

LRESULT CGameView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	MsgHan.Lock();
	
	gActive = true;
	gGotFocus= true;
	if(!BadEngine)
		switch(message)
	{
	case WM_MOUSELEAVE:
			CameraController::GetInstance()->RBMode=false;
		break;
	case WM_PAINT:
		//		ValidateRect(NULL);
	case WM_ACTIVATE:
	case WM_SETFOCUS:
		
		//	case WM_CHAR:
		//	case WM_KEYDOWN:
		
	case WM_MOVE:
		GameOSWinProc(m_hWnd, message, wParam, lParam);
		break;
	case WM_RBUTTONDOWN:
		CameraController::GetInstance()->RBMode=true;
	case WM_LBUTTONDOWN:
		SetCapture();
		GameOSWinProc(m_hWnd, message, wParam, lParam);
		break;
	case WM_RBUTTONUP:
		CameraController::GetInstance()->RBMode=false;
	case WM_LBUTTONUP:
		ReleaseCapture();
		GameOSWinProc(m_hWnd, message, wParam, lParam);
		break;
		
	}
	
	LRESULT res=CWnd::WindowProc(message, wParam, lParam);
	MsgHan.Unlock();
	return res;
}


void CGameView::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	UpdateDisplay();
	//	_beginthread(UpdateThreadFun,0,(void *)this);
	// TODO: Add your message handler code here
	
	// Do not call CWnd::OnPaint() for painting messages
}


void CGameView::UpdateDisplay()
{
	if(IsWindowVisible() && !InLogic && !DisplayOff && !BadEngine && ObjMan->IsLoaded())
	{
		InLogic=true;
		if(ObjMan!=NULL)
		{
			bool res1;
			res1=ObjMan->GetCameraController()->ProcessIO();
			ObjMan->GetCameraController()->UpdateCamera();
			if(res1)
				Refresher::Instance->OverviewRefresh();
		}	
		
			__try
			{
				if(RunGameOSLogic())
					PostQuitMessage(0);

			}
			__except(ProcessException(GetExceptionInformation())
#ifndef _DEBUG
				,EXCEPTION_EXECUTE_HANDLER
#endif
			)
			{
			MessageBox("The Game Engine has become unstable and will no longer be active\nIt is suggested that you restart the editor. Saving after this point can possible corrupt data.\n!!CONTINUE AT RISK OF DATA CORRUPTION!!","Game Error",MB_OK);
			BadEngine=true;
			}
		
		InLogic=false;
	}
	
}	

void CGameView::OnFileClose() 
{
	ShowWindow(SW_HIDE);
}

void CGameView::OnSetFocus(CWnd* pOldWnd) 
{
	CWnd::OnSetFocus(pOldWnd);
}

void CGameView::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	
	ShowWindow(SW_HIDE);
	//	CWnd::OnClose();
}




CPoint CGameView::GetInvalidStartPoint()
{
	return (CPoint(-1,-1));
}

Stuff::Scalar CGameView::SetAttribute_Absolute(int cur_value, int window_size, Stuff::Scalar min_value, Stuff::Scalar max_value)
{
	Stuff::Scalar rv((Stuff::Scalar)cur_value / (Stuff::Scalar)window_size);
	
	rv *= (max_value - min_value);
	rv += min_value;
	
	return (rv);
}

Stuff::Scalar CGameView::SetAttribute_Rollover(Stuff::Scalar original_value, int cur_value, int start_value, int window_size, Stuff::Scalar min_value, Stuff::Scalar max_value)
{
	Stuff::Scalar normalized_start((Stuff::Scalar)start_value / (Stuff::Scalar)window_size);
	Stuff::Scalar normalized_current((Stuff::Scalar)cur_value / (Stuff::Scalar)window_size);
	
	normalized_current = normalized_start - normalized_current;
	
	while (normalized_current < 0)
	{
		normalized_current += 1.0f;
	}
	
	while (normalized_current >= 1)
	{
		normalized_current -= 1.0f;
	}
	
	Stuff::Scalar current(normalized_current * (max_value - min_value));
	current += min_value;
	
	current += original_value;
	
	while (current >= max_value)
	{
		current -= (max_value - min_value);
	}
	
	while (current < min_value)
	{
		current += (max_value - min_value);
	}
	
	return (current);
}

void CGameView::ZoomYaw(int x, int y)
{
	RECT r;
	GetWindowRect(&r);
	
	Stuff::YawPitchRange ypr(m_SavedYPR);
	
	ypr.range = SetAttribute_Absolute(y,
		r.bottom - r.top,
		ObjMan->GetCameraController()->GetMinDistance(),
		ObjMan->GetCameraController()->GetMaxDistance());
	
	ypr.yaw = SetAttribute_Rollover(m_SavedYPR.yaw,
		x,
		m_ZoomYawOrigin.x,
		r.right - r.left,
		ObjMan->GetCameraController()->GetMinYaw(),
		ObjMan->GetCameraController()->GetMaxYaw());
	
	SetNewYPR(ypr);
}

void CGameView::PitchYaw(int x, int y)
{
	RECT r;
	GetWindowRect(&r);
	
	Stuff::YawPitchRange ypr(m_SavedYPR);
	
	ypr.pitch = SetAttribute_Absolute(y,
		r.bottom - r.top,
		ObjMan->GetCameraController()->GetMinPitch(),
		ObjMan->GetCameraController()->GetMaxPitch());
	
	ypr.yaw = SetAttribute_Rollover(m_SavedYPR.yaw,
		x,
		m_PitchYawOrigin.x,
		r.right - r.left,
		ObjMan->GetCameraController()->GetMinYaw(),
		ObjMan->GetCameraController()->GetMaxYaw());
	SetNewYPR(ypr);
}

void CGameView::SetNewYPR(const Stuff::YawPitchRange& ypr)
{
	if ((ObjMan != 0) &&
		(ObjMan->GetCameraController() != 0) &&
		(ObjMan->GetCameraController()->StaysInsideBounds(ObjMan->GetCameraController()->GetLookAt(),ypr) == true))
	{
		ObjMan->GetCameraController()->SetYawPitchRange(ypr);
		ObjMan->GetCameraController()->Update();
	}
	
	if (Refresher::Instance != 0)
	{
		Refresher::Instance->DrawRefresh();
	}
}

void CGameView::OnMouseMove(UINT nFlags, CPoint point) 
{
	if ((ObjMan == 0) ||
		(ObjMan->GetCameraController() == 0))
	{
		return;
	}
	
	CRect crect;	
	GetClientRect(&crect);
	CSize delta;
	delta=OldPoint-point;

	if(CameraController::GetInstance()->RevMouse)
		delta.cy=-delta.cy;
	
		if(nFlags&MK_RBUTTON)
		{
			YawPitchRange ypr=CameraController::GetInstance()->GetYawPitchRange();
			CameraController::GetInstance()->RBMode=true;

			Scalar yd=(float)(delta.cy)*Two_Pi/crect.Height();
			Scalar xd=(float)(delta.cx)*Two_Pi/crect.Width();
			ypr.yaw+=xd;
			ypr.pitch+=yd;
			CameraController::GetInstance()->SetYawPitchRange(ypr);
			CameraController::GetInstance()->Update();
			Refresher::Instance->DrawRefresh();
			
		}
		else
		{
		CameraController::GetInstance()->RBMode=false;

		}
		
		OldPoint=point;
	CWnd::OnMouseMove(nFlags, point);
}

void CGameView::OnSize(UINT nType, int cx, int cy) 
{
	if(!InLogic && !DisplayOff) gos_SetScreenMode(cx,cy);
	
}

void CGameView::FixDisplayWindow()
{
	CRect crct;
	GetClientRect(&crct);
	gos_SetScreenMode(crct.Width(),crct.Height());
	
}

