//=========================================================================
// CPAProject.cpp : Defines the class behaviors for the application.
// This is a part of the CPA project.
//
// Version              1.0
// Creation date        06/06/96
// Revision date
//
// (c) Ubi Studios 1996
//
// DO NOT MODIFY THAT FILE. IF SOMETHING NEEDS TO BE CHANGE, PLEASE CONTACT
// VINCENT GRECO OR CHRISTOPHE BEAUDET.
//=========================================================================

#include "stdafx.h"
#include "acp_base.h"

#define __DeclareGlobalVariableErrInt_h__
#include "ErrInt.h"
#undef __DeclareGlobalVariableErrInt_h__
#define __DeclareGlobalVariableMmgInt_h__
#include "MmgInt.h"
#undef __DeclareGlobalVariableMmgInt_h__

#include "direct.h"
#undef EXTERN
#include "geo.h"
#include "gli.h"
#include "col.h"
#define HieFriend
#include "spo.h"
#include "lst.h"
#undef HieFriend

#include "Itf/CPARes.h"
#include "Itf/CPAProj.hpp"
#include "Itf/CPADoc.hpp"
#include "Itf/DEVMul3D.hpp"
#include "Itf/FRMGest.Hpp"
#include "Itf/CPACont.hpp"
#include "Itf/CPAConst.hpp"
#include "Itf/CPAkacnf.hpp"
#include "Itf/cpamworl.hpp"
#include "Itf/cpakacnf.hpp"
#include "Itf/CPAAbout.hpp"
#include "Itf/CPAInter.hpp"

/////////////////////////////////////////////////////////////////////////////
// CPA_ProjectApp

BEGIN_MESSAGE_MAP(CPA_ProjectApp, CWinApp)
	//{{AFX_MSG_MAP(CPA_ProjectApp)
		ON_THREAD_MESSAGE(WM_USER,OnUserMsg)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG
END_MESSAGE_MAP()


//###########################################################################
//      Constructor and destructor of application
//###########################################################################

//===========================================================================
//      Description:    CONSTRUCTOR
//                                      => Change windows parameters
//      Creation date:  27 Jun 96
//      Author:         CB
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
CPA_ProjectApp::CPA_ProjectApp()
{
	//---------------------------------------------------------------------------
	// memory and error messages initialisations
    // For memory usage and errors
    Erm_M_InitErrMsg(Erm);
    Erm_M_InitErrMsg(Mmg);
    Erm_M_InitErrMsg(Int);
    Mmg_fn_vFirstInitMmgModule(10);
    Mmg_M_InitMmg(Int);
	m_bWasInFullScreenBeforeLooseFocus = FALSE;
	m_bLeavingApplication = FALSE;
	m_bBadResolution = FALSE;
	m_bFlagTaken = FALSE;
	//---------------------------------------------------------------------------

    m_bProjectIsClosing = 0;


	m_bEngineIsStopped = FALSE;
	m_bEditorsAreActive = FALSE;
	m_bAppliAskedToStopEngine = FALSE;
	m_bAppliPulsedOneStep = FALSE;
	m_bAppliAskedToActivateEditors = FALSE;
	m_bEngineAskedToForceEditors = FALSE;
	m_bAppliAskedToEndGame = FALSE;		
	m_bEngineIsOver = FALSE;			
	m_bFinishEngine = FALSE;			
}

//===========================================================================
//      Description:    DESTRUCTOR
//                                      => Kill all editors
//                                      => Restore windows parameters
//      Creation date:  27 Jun 96
//      Author:         CB
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
CPA_ProjectApp::~CPA_ProjectApp()
{
}

//###########################################################################
// CPA_ProjectApp initializations and close
//###########################################################################


//===========================================================================
//      Description:    Set and reset windows parameters.
//      Creation date:  27 Jun 96
//      Author:         CB
//---------------------------------------------------------------------------
//      Return void
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
void CPA_ProjectApp::fn_vSetWindowsParameters(void)
{
    // => No screen saver
/*    SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &m_bOldScreenSaveActive, 0);
    SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0);*/
}
void CPA_ProjectApp::fn_vResetWindowsParameters(void)
{
    // => Screen saver
    //SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, m_bOldScreenSaveActive, NULL, 0);
}

//===========================================================================
//      Description:    Test windows config. to be sure that it's correct for
//                      game.
//                      Fatal error if not correct.
//      Creation date:  27 Jun 96
//      Author:         CB
//---------------------------------------------------------------------------
//      Return void
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
void CPA_ProjectApp::fn_vTestWindowsConfig(void)
{
    HDC             hdc;
    int             iAppBPP;

    hdc = ::GetDC(NULL);
    iAppBPP = ::GetDeviceCaps(hdc, PLANES);
    iAppBPP *= ::GetDeviceCaps(hdc, BITSPIXEL);
    ::ReleaseDC(NULL, hdc);

	if(iAppBPP != 16)
		m_bBadResolution = TRUE;
}

//===========================================================================
//      Description:    Init camera to see the world correctly
//      Creation date:  05 sept 96
//      Author:         FBF
//---------------------------------------------------------------------------
//      Return niet
//---------------------------------------------------------------------------
//      Revision date: ?
//      Author:
//===========================================================================

//===========================================================================
//      Description:    First init of application.
//      Creation date:  21 Jun 96
//      Author:         CB
//---------------------------------------------------------------------------
//      Return BOOL
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
extern "C"
{
    long  (*GLI_DRV_lSendDataToDll)(char *, void *);
}

BOOL CPA_ProjectApp::InitApplication(void)
{

    //  Change protection of EXE if there's auto generate code, and virtual lock
    //  code.
    //  fn_vChangeExeProtection((unsigned long) m_hInstance);

    // Test windows environment
    fn_vTestWindowsConfig();

    // Change windows parameters
    fn_vSetWindowsParameters();

    // Create all semaphores
    m_hDrawSem = CreateSemaphore(NULL, 1, 1, (LPCTSTR) "DRAWSEM");
    GLI_DRV_lSendDataToDll("DrawSem", m_hDrawSem );

    // To avoid list of dump memory at the end of execution
    AfxEnableMemoryTracking(FALSE);

	//FBFFBF temporaire V3.1, à virer ds la prochaine version
	HIE_fn_vInitGlobalMatrixFrameCounter(3);

    return CWinApp::InitApplication();
}

//===========================================================================
//      Description:    Last exit of application.
//      Creation date:  27 Jun 96
//      Author:         CB
//---------------------------------------------------------------------------
//      Return BOOL
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
void CPA_ProjectApp::ExitApplication(void)
{
	ClipCursor(NULL);
	// show cursor
	while (ShowCursor(TRUE) < 0);

	m_bLeavingApplication = TRUE;

    // Free all semaphores
    CloseHandle(m_hDrawSem);

    // Restore windows parameters
    fn_vResetWindowsParameters();

}

//===========================================================================
//      Description:    Call for each new instance of application.
//      Creation date:  10 Jun 96
//      Author:         CB
//---------------------------------------------------------------------------
//      Return void
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
BOOL CPA_ProjectApp::InitInstance()
{

	// Register document templates
    CSingleDocTemplate*     pDocTemplate;
    pDocTemplate = new CSingleDocTemplate(
    	CPA_IDR_MAINFRAME,
    	RUNTIME_CLASS(CPA_ProjectDoc),
    	RUNTIME_CLASS(CPA_MainFrame),
    	RUNTIME_CLASS(DEV_MultiDevice3D));
    AddDocTemplate(pDocTemplate);

    //
    // Add all DLLs to list.
    //

    // New file
    OnFileNew();
    if (m_pMainWnd == NULL)
    	return FALSE;
    m_nCmdShow = SW_SHOWNORMAL;
	
	if (GLI_lWhatIsGLI() != GLI_C_VersionGlide)
	{
		M_GetMainDevice()->GetDevice(0)->AfterCreate();
	}

	// Clear main device
	GLD_bClearDevice(M_GetMainDevice()->GetDevice(0)->m_hDisplayDevice);
	GLD_bFlipDevice(M_GetMainDevice()->GetDevice(0)->m_hDisplayDevice);

    // Special frame


    //
    // Create a new process for engine
    //
    fn_vCreateEngineThread();
	M_GetMainWnd()->SetFocus();
	if (GLI_lWhatIsGLI() != GLI_C_VersionGlide)
	{
		m_p_oEngineThread->ResumeThread();
	}

#ifdef NDEBUG
	while (ShowCursor(FALSE) >= 0);
#endif


    return TRUE;
}

//###########################################################################
//###########################################################################
BOOL CPA_ProjectApp::PreTranslateMessageEditor(MSG *p_stMsg)
{
	return FALSE;
}

//###########################################################################
//###########################################################################
void CPA_ProjectApp::BeforeWindows()
{
	if (m_p_oEngineThread == NULL)
		return;
	if (WaitForSingleObject(m_hDrawSem,10000) == WAIT_TIMEOUT)
		ASSERT(0);
	ASSERT(m_p_oEngineThread->SuspendThread() >= 0);
	ReleaseSemaphore(m_hDrawSem,1,NULL);
}

//###########################################################################
//###########################################################################
void CPA_ProjectApp::AfterWindows()
{
	if (m_p_oEngineThread == NULL)
		return;
	if (WaitForSingleObject(m_hDrawSem,10000) == WAIT_TIMEOUT)
		ASSERT(0);
	ReleaseSemaphore(m_hDrawSem,1,NULL);
	m_p_oEngineThread->ResumeThread();
}

//###########################################################################
//###########################################################################
extern BOOL GLD_fn_bCanBeWindowed( void );

void fnv_SwapFullScreen(void)
{
    /*
     * Device is in full screen
     */
    if (M_GetMainDevice()->GetDevice(0)->IsFullScreen())
    {
        M_GetMainDevice()->GetDevice(0)->SwapFullScreen();
        /*
         * can't be windowed
         */
        if (M_GetMainApp()->m_bBadResolution || !GLD_fn_bCanBeWindowed() )
        {
		    M_GetMainApp()->fn_vAppliAskToStopEngine();
		    M_GetMainApp()->m_bWasInFullScreenBeforeLooseFocus = TRUE;
		    M_GetMainWnd()->SendMessage(WM_SYSCOMMAND, SC_MINIMIZE);
        }
    }
    /*
     * device is windowed or minimized
     */
    else
    {
        /*
         * can't be windowed
         */
        if(M_GetMainWnd()->IsIconic())
		    M_GetMainWnd()->SendMessage(WM_SYSCOMMAND, SC_RESTORE);

        M_GetMainDevice()->GetDevice(0)->SwapFullScreen();
        M_GetMainApp()->m_bWasInFullScreenBeforeLooseFocus = FALSE;
    }
	
    /*
    if((M_GetMainApp()->m_bBadResolution) && (M_GetMainDevice()->GetDevice(0)->IsFullScreen()))
	{
		M_GetMainApp()->fn_vAppliAskToStopEngine();
		M_GetMainDevice()->GetDevice(0)->SwapFullScreen();
		M_GetMainApp()->m_bWasInFullScreenBeforeLooseFocus = TRUE;
		M_GetMainWnd()->SendMessage(WM_SYSCOMMAND, SC_MINIMIZE);
	}
	else
	{
		if(M_GetMainDevice()->GetDevice(0)->IsFullScreen())
		{
			if(M_GetMainWnd()->IsIconic())
				M_GetMainWnd()->SendMessage(WM_SYSCOMMAND, SC_RESTORE);
			M_GetMainApp()->m_bWasInFullScreenBeforeLooseFocus = FALSE;
		}
		M_GetMainDevice()->GetDevice(0)->SwapFullScreen();
	}
    */
}

//###########################################################################
//###########################################################################
BOOL CPA_ProjectApp::PreTranslateMessageEngine(MSG *p_stMsg)
{
	BOOL    bRes = FALSE;
	static BOOL bMenu = FALSE;
	
	BeforeWindows();
	switch(p_stMsg->message)
	{
	/*
	 * Want to restore window. If window was in full screen before been minimized,
	 * for to swap to full screen.
	 */
	case WM_SYSCOMMAND:
		switch(p_stMsg->wParam)
		{
		case SC_RESTORE:
		case SC_MAXIMIZE:
			if(m_bWasInFullScreenBeforeLooseFocus)
				fnv_SwapFullScreen();
			break;
		}
		break;

	case WM_SYSKEYUP:
		switch(p_stMsg->wParam)
		{
		case VK_RETURN:
			fnv_SwapFullScreen();
			bRes = TRUE;
			break;
			
		case VK_TAB:
			M_GetMainApp()->fn_vAppliAskToStopEngine();
			if (M_GetMainDevice()->GetDevice(0)->IsFullScreen())
				fnv_SwapFullScreen();
			bRes = TRUE;
			break;
			
		case VK_F10:
			bRes = TRUE;
			break;
		}
		break;
		
		// Keyboard messages
		case WM_KEYDOWN:
		case WM_KEYUP:
		case WM_CHAR:
		case WM_DEADCHAR:
			if (p_stMsg->wParam == VK_NUMLOCK || 
				p_stMsg->wParam == VK_SCROLL || 
				p_stMsg->wParam == VK_CAPITAL ||
				p_stMsg->wParam == VK_SHIFT ||
				p_stMsg->wParam == VK_LSHIFT ||
				p_stMsg->wParam == VK_RSHIFT)
				bRes = FALSE;
			else
				bRes = TRUE;
			break;
			
		// No mouse messages
		case WM_LBUTTONDOWN:
		case WM_RBUTTONDOWN:
		case WM_LBUTTONUP:
		case WM_RBUTTONUP:
		case WM_MOUSEMOVE:
		case WM_LBUTTONDBLCLK:
		case WM_RBUTTONDBLCLK:
			bRes = TRUE;
			break;
			
		default:
			bRes = FALSE;
			break;
	}
	AfterWindows();
	return bRes;
}

//###########################################################################
//###########################################################################
BOOL CPA_ProjectApp::PreTranslateMessage( MSG* pMsg )
{
	BOOL bRes;
	
	//call base member
	bRes = CWinApp::PreTranslateMessage(pMsg);
	if (!bRes)
	{
		bRes = CPA_ProjectApp::PreTranslateMessageEngine(pMsg);
	}
	return bRes;
}

//###########################################################################
//###########################################################################
int CPA_ProjectApp::Run(void)
{
	MSG     stMsg;
    BOOL    bRes;

	// loop while message is not WM_QUIT
    while (::GetMessage(&stMsg, NULL, 0, 0))
    {
        if (stMsg.message == WM_CANCELMODE)
        {
            fnv_SwapFullScreen();
        }
		bRes = PreTranslateMessage(&stMsg);
		if(!bRes)
		{
			::TranslateMessage(&stMsg);
			::DispatchMessage(&stMsg);
		}
    }
	
    // Application exit code
    ExitApplication();
	
    return stMsg.wParam;
}

//===========================================================================
//  Description:    Called by the appli when the appli wants to stop the engine
//	result :
//				The Engine has not been stopped, but it has been notified to do so. We will receive a
//				user message when the engine wants to be stopped		
//  Creation date:  19 jun 97
//  Author:         FBF
//---------------------------------------------------------------------------
//  Revision date:
//  Author:
//===========================================================================
void CPA_ProjectApp::fn_vAppliAskToStopEngine(void)
{
	m_bAppliAskedToStopEngine = TRUE;
}


//===========================================================================
//  Description:    Called by the appli when the appli wants to start the engine
//	result :
//				The Engine will restart
//  Creation date:  19 jun 97
//  Author:         FBF
//---------------------------------------------------------------------------
//  Revision date:
//  Author:
//===========================================================================
void CPA_ProjectApp::fn_vAppliAskToStartEngine(void)
{
	m_bAppliAskedToStopEngine = FALSE;

	if (m_bEngineIsStopped)
		fn_vRestartEngine();
}

//===========================================================================
//  Description:    Called by the appli when the appli wants to start the engine
//                  for one step
//  Creation date:  aujourd'hui
//  Author:         VL mais j'avoue avoir copié la fonction de FBF de CpaProj.cpp
//                  par contre j'aime pas du tout le style des commentaires mais
//                  c'est plutot personnel
//===========================================================================
void CPA_ProjectApp::fn_vAppliAskOneStep(void)
{
	// pulse if engine has been stopped by the appli and if the engine is stopped and if one step has not allready been asked
	if ((m_bAppliAskedToStopEngine == TRUE) && (m_bEngineIsStopped == TRUE) && (m_bAppliPulsedOneStep == FALSE))
	{
		m_bAppliPulsedOneStep = TRUE;
		fn_vRestartEngine();
	}
}

//===========================================================================
//  Description:    Called by the appli when the appli wants to end the game
//	result :
//				The Engine has been notified to begin the closing process
//				we will receive a user message when the engine begin this process,
//				and when the engine has finished this process

//  Creation date:  19 jun 97
//  Author:         FBF
//---------------------------------------------------------------------------
//  Revision date:
//  Author:
//===========================================================================
void CPA_ProjectApp::fn_vAppliAskToEndGame(void)
{
	// tell that we want to close
	m_bAppliAskedToEndGame = TRUE;
	// if editors are active, then we must restart the engine so that it can close
	// to allow the engine to restart
	M_GetMainApp()->m_bEditorsAreActive = FALSE;
	// to prevent the engine from going back to editors
	M_GetMainApp()->m_bAppliAskedToActivateEditors = FALSE;

	M_GetMainApp()->fn_vRestartEngine();

}

//===========================================================================
//  Description:    a user message has been received
//	return value:
//  Creation date:  19 jun 97
//  Author:         FBF
//---------------------------------------------------------------------------
//  Revision date:
//  Author:
//===========================================================================
afx_msg void CPA_ProjectApp::OnUserMsg(UINT wParam,LONG lParam)
{
	// structure for Message box request
	tdstMsgBox * p_stMsgBox;

	switch(wParam)
	{
	case C_uiWinCm_RequestMessageBox:
		
		p_stMsgBox = (tdstMsgBox*) lParam;
		
		SendMessage(m_pMainWnd->m_hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
		p_stMsgBox->iResult = MessageBox(NULL,p_stMsgBox->szText,p_stMsgBox->szTitle,p_stMsgBox->uiStyle);
		SendMessage(m_pMainWnd->m_hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
//		SetEvent(p_stMsgBox->hEvent);
		break;

	case USERM_STOP_ENGINE:
		// if the flag is not right, do nothing
		if (m_bAppliAskedToStopEngine == FALSE)
			break;
		fn_vStopEngine();
		break;

	case USERM_ENGINE_IS_CLOSING:
		m_bLeavingApplication = TRUE;
		break;

	case USERM_ENGINE_IS_DONE:
		m_bLeavingApplication = TRUE;
		m_bEngineIsOver = TRUE;
		m_bFinishEngine = TRUE;
		M_GetMainWnd()->PostMessage(WM_CLOSE,0,0);
		break;

	case USERM_SWAP_FULLSCREEN:
		fnv_SwapFullScreen();
		break;
	}
}

//===========================================================================
//  Description:    Stops the engine
//	return value:
//  Creation date:  19 jun 97
//  Author:         FBF
//---------------------------------------------------------------------------
//  Revision date:
//  Author:
//===========================================================================
void CPA_ProjectApp::fn_vStopEngine()
{
	// if the engine is allready stopped, do nothing
	if (m_bEngineIsStopped)
		return;
	// stop the engine
	VERIFY(m_p_oEngineThread->SuspendThread() >= 0);
	m_bEngineIsStopped = TRUE;
}

//===========================================================================
//  Description:    resume the engine
//	return value:
//  Creation date:  19 jun 97
//  Author:         FBF
//---------------------------------------------------------------------------
//  Revision date:
//  Author:
//===========================================================================
void CPA_ProjectApp::fn_vRestartEngine()
{
	// if engine runs, do nothing
	if (!m_bEngineIsStopped)
		return;

	ASSERT(m_bEditorsAreActive == FALSE);
	if (m_p_oEngineThread)
	{
		m_bEngineIsStopped = FALSE;
		m_p_oEngineThread->ResumeThread();
	}
}


