/*=========================================================================
* 
* CPAdIns.cpp :  Insertion - Implementation file
* 
*
* Version			1.0
* Creation date		
* Revision date
*
* Shaitan
*=======================================================================*/

#include "stdafx.h"
#ifdef ACTIVE_EDITOR

#include "acp_base.h"
#include "itf/CPAdIns.hpp"
#include "itf/CPADD.hpp"
#include "itf/DEVVp3D.hpp"
#include "itf/DEVMul3D.hpp"
#include "itf/CPAProj.hpp"
#include "itf/CPAInter.hpp"
#include "itf/CPAMWorl.hpp"

#include "x:\cpa\main\inc\_EditID.h"
#include "TUT.h"
#include <direct.h>



//#################################################################################
// CPA_DialogInsert dialog
//#################################################################################

/*----------------------------------------
----------------------------------------*/
CPA_DialogInsert::CPA_DialogInsert(CWnd* pParent)
	: CFormView(CPA_DialogInsert::IDD)
{
	//{{AFX_DATA_INIT(CPA_DialogInsert)
	//}}AFX_DATA_INIT
}

/*----------------------------------------
----------------------------------------*/
void CPA_DialogInsert::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPA_DialogInsert)
	DDX_Control(pDX, CPA_IDC_NEWMODEL, m_cNewModel);
	DDX_Control(pDX, CPA_IDC_DELMODEL, m_cDelModel);
	DDX_Control(pDX, CPA_IDC_CHANGEICON, m_cModelIcon);
	DDX_Control(pDX, CPA_IDC_SAVELIST, m_cSaveList);
	DDX_Control(pDX, CPA_IDC_LOADLIST, m_cLoadList);
	DDX_Control(pDX, CPA_IDC_COMBOTYPE, m_cComboType);
	//}}AFX_DATA_MAP
}

/*----------------------------------------
----------------------------------------*/
BEGIN_MESSAGE_MAP(CPA_DialogInsert, CFormView)
	//{{AFX_MSG_MAP(CPA_DialogInsert)
	ON_CBN_SELCHANGE(CPA_IDC_COMBOTYPE, OnSelchangeCombotype)
	ON_BN_CLICKED(CPA_IDC_NEWMODEL, OnNewModel)
	ON_BN_CLICKED(CPA_IDC_DELMODEL, OnDelModel)
	ON_BN_CLICKED(CPA_IDC_CHANGEICON, OnModelIcon)
	ON_BN_CLICKED(CPA_IDC_SAVELIST, OnSaveList)
	ON_BN_CLICKED(CPA_IDC_LOADLIST, OnLoadList)
    ON_WM_SIZE()
    ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


//#################################################################################
// CPA_DialogInsert dialog
//#################################################################################

/*===========================================================================
*		Description:	Init the dialog
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                 Author:         
*=========================================================================*/
void CPA_DialogInsert::fn_vInitDialog (CPA_Interface *pInterface, FRMBase *pFrame)
{
	// create the dialog
	m_bInitialised = FALSE;
	m_p_oInterface = pInterface;
	CFormView::Create(NULL, "", WS_VISIBLE|WS_CHILD/*AFX_WS_DEFAULT_VIEW*/, CRect(0,0,0,0), pFrame, AFX_IDW_PANE_FIRST, NULL);

	// update data
	CFormView::UpdateData(FALSE);
	// init the combo box
	GetInterface()->SetCurrentModel(NULL);
	m_csTypeInsert = "All Types";
	
	// init the list box
	m_iNumDesc = -1;
	m_pListModels = NULL;
	m_lNbValidNew = 0;
	m_lNbValidLoad = 0;
	m_ePopupMode = E_pm_NoMode;
	m_bInitialised = TRUE;

    // register controls
    TUT_M_vGetTutDll();
    TUT_M_vRegisterControlID( CPA_IDC_NEWMODEL,		"ITF_MODEL_BTNEW",	TUT_e_Button );
    TUT_M_vRegisterControlID( CPA_IDC_DELMODEL,		"ITF_MODEL_BTDEL",	TUT_e_Button );
    TUT_M_vRegisterControlID( CPA_IDC_CHANGEICON,	"ITF_MODEL_BTICON",	TUT_e_Button );
    TUT_M_vRegisterControlID( CPA_IDC_SAVELIST,		"ITF_MODEL_BTSAVE", TUT_e_Button );
    TUT_M_vRegisterControlID( CPA_IDC_LOADLIST,		"ITF_MODEL_BTLOAD",	TUT_e_Button );
    TUT_M_vRegisterControlID( CPA_IDC_COMBOTYPE,	"ITF_MODEL_CBTYPE",	TUT_e_ComboBox );
}
	

/*===========================================================================
*		Description:	init the combo box
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                   Author:         
*=========================================================================*/
void CPA_DialogInsert::fn_vInitComboType (CString csListName)
{
	CPA_ObjectDLLBase	*p_oDLL;
	EDT_ModelsByType	*pListType;
	POSITION			pos;
	int					iInd;

	// RAZ
	m_cComboType.ResetContent();
	m_lNbValidNew = 0;
	m_lNbValidLoad = 0;

	m_cComboType.AddString("All Types");
	
	// fill the list of the combo with the available types
	for (pListType = GetInterface()->GetListOfModelsByType()->GetHeadElement(pos); pListType; 
		 pListType = GetInterface()->GetListOfModelsByType()->GetNextElement(pos))
		m_cComboType.AddString(pListType->GetTypeName());
	// set the current selection (Select Mode)
	if (csListName.IsEmpty())
	{
		m_csTypeInsert = "All Types";
		m_cComboType.SetCurSel(0);
	}
	else
	{
		m_csTypeInsert = csListName;
		iInd = m_cComboType.FindStringExact(-1, csListName);
		m_cComboType.SetCurSel(iInd);
	}

	// update flags
	iInd = 0;
	do 
	{
		p_oDLL = M_GetMainWorld()->GetListOfObjectDLLBase()->FindElementFromIndex(iInd);
		if ((p_oDLL)&&(p_oDLL->fn_bCanLoadNewModel("All Types")))
			m_lNbValidNew++;
		if ((p_oDLL)&&(p_oDLL->fn_bCanLoadListModels()))
			m_lNbValidLoad++;
		iInd++;
	}
	while (p_oDLL);

	// update the list
	fn_vUpdateListModel();
}

/*===========================================================================
*		Description:	init the combo box
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                   Author:         
*=========================================================================*/
void CPA_DialogInsert::fn_vSetCurrentListModel (CString csListName)
{
	int iInd;
	
	// set the current selection (Select Mode)
	iInd = m_cComboType.FindStringExact(-1, csListName);
	if (iInd != -1)
	{
		m_csTypeInsert = csListName;
		m_cComboType.SetCurSel(iInd);
	}
	else
	{
		m_csTypeInsert = "All Types";
		m_cComboType.SetCurSel(0);
	}
	// update the list
	fn_vUpdateListModel();
}


/*===========================================================================
*		Description:	init the list box
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:               Author:         
*=========================================================================*/
void CPA_DialogInsert::fn_vReinitListModel (void)
{
    RECT AbsolutePosition, WindowPosition; 
	int px, py, cx, cy;

	// Calculate the position of the dialog
	GetDlgItem(CPA_IDC_NEWDIALOG)->GetWindowRect(&AbsolutePosition);
    GetWindowRect(&WindowPosition);
    px = AbsolutePosition.left - WindowPosition.left;
    py  = AbsolutePosition.top  - WindowPosition.top;
	cx =  WindowPosition.right - WindowPosition.left - 2*px;
	cy = WindowPosition.bottom - WindowPosition.top - py - 10;
	
	// move the new dialog
    if (m_pListModels)
	{
		m_pListModels->MoveWindow(px, py , cx, cy);  
		m_pListModels->ShowWindow(SW_SHOW);
		m_pListModels->EnableWindow(TRUE);
		m_pListModels->Invalidate();
	}
}

/*===========================================================================
*		Description:	update the list of models
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:               Author:         
*=========================================================================*/
void CPA_DialogInsert::fn_vUpdateListModel (void)
{
	EDT_ModelsByType	*pListType;

	// get list by type
	pListType = GetInterface()->GetModelsWithTypeName(m_csTypeInsert);
	if (!pListType)
		pListType = GetInterface()->GetListAllModels();
	// get model view
	if (m_pListModels)
	{
		m_pListModels->ShowWindow(SW_HIDE);
		m_pListModels->EnableWindow(FALSE);
	}
	m_pListModels = pListType->m_pModelView;
	fn_vReinitListModel();
	
	GetInterface()->SetCurrentModel(NULL);

	// reinit controls
	if (pListType != GetInterface()->GetListAllModels())
	{
		// init button "Del"
		m_cDelModel.EnableWindow(pListType->CanDeleteModel());
		// init button "New"
		m_cNewModel.EnableWindow(pListType->CanLoadNewModel());
		// init button "Icon"
		m_cModelIcon.EnableWindow(pListType->CanChangeModelIcon());
		// init button "Save"
		m_cSaveList.EnableWindow(pListType->CanSaveList());
	}
	else
	{
		m_cDelModel.EnableWindow(FALSE);
		m_cModelIcon.EnableWindow(FALSE);
		m_cNewModel.EnableWindow((m_lNbValidNew > 0));
		m_cSaveList.EnableWindow(FALSE);
	}
	// init button "Load"
	m_cLoadList.EnableWindow((m_lNbValidLoad > 0));

	// Update the current object to insert
	if (m_pListModels->m_fn_lGetCount())
		m_iNumDesc = 0;
	else
		m_iNumDesc = -1;
}

/*===========================================================================
*		Description:	load new model
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:               Author:         
*=========================================================================*/
void CPA_DialogInsert::fn_vLoadNewModel (CPA_ObjectDLLBase *p_oDLL)
{
	EDT_Model	*pNewModel;
	BOOL		bRes;

	if (!p_oDLL)
		return;
	
	// call the corresponding load function
	pNewModel = p_oDLL->GetNewModel(m_csTypeInsert);

	// test the type
	if (pNewModel)
	{
		bRes = GetInterface()->fn_bAddANewModel(pNewModel, m_csTypeInsert, p_oDLL);
		// test unicity
		if (!bRes)
		{
			M_GetMainWnd()->MessageBox("This descriptor is already loaded",
									"Sorry...", MB_ICONSTOP|MB_OK);
			delete pNewModel;
			return;
		}
		// update the list box
		m_pListModels->Invalidate();
		// update selection
		GetInterface()->SetCurrentModel(pNewModel);
		GetInterface()->fn_vUpdateAll(E_mc_UpdateDialog);
	}
}

/*===========================================================================
*		Description:	load model list
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:               Author:         
*=========================================================================*/
void CPA_DialogInsert::fn_vLoadListModels (CPA_ObjectDLLBase *p_oDLL)
{
	CString csNewList;
	
	if (p_oDLL)
		csNewList = p_oDLL->fn_csLoadListModels();
	
	// if there's a new list, update dialog
	if (!csNewList.IsEmpty())
		fn_vInitComboType(csNewList);
}

/*===========================================================================
*		Description:	load model list
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:               Author:         
*=========================================================================*/
CPA_ObjectDLLBase * CPA_DialogInsert::GetSingleDllForNew (void)
{
	CPA_ObjectDLLBase	*p_oDLL;
	long				lIndex = 0;
	
	do 
	{
		p_oDLL = M_GetMainWorld()->GetListOfObjectDLLBase()->FindElementFromIndex(lIndex);
		if ((p_oDLL)&&(p_oDLL->fn_bCanLoadNewModel(m_csTypeInsert)))
			return p_oDLL;
		lIndex++;
	}
	while (p_oDLL);

	return NULL;
}

/*===========================================================================
*		Description:	load model list
*		Creation date:	
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:               Author:         
*=========================================================================*/
CPA_ObjectDLLBase * CPA_DialogInsert::GetSingleDllForLoad (void)
{
	CPA_ObjectDLLBase	*p_oDLL;
	long				lIndex = 0;
	
	do 
	{
		p_oDLL = M_GetMainWorld()->GetListOfObjectDLLBase()->FindElementFromIndex(lIndex);
		if ((p_oDLL)&&(p_oDLL->fn_bCanLoadListModels()))
			return p_oDLL;
		lIndex++;
	}
	while (p_oDLL);

	return NULL;
}

//#################################################################################
// CPA_DialogInsert message handlers
//#################################################################################

/*----------------------------------------
----------------------------------------*/
void CPA_DialogInsert::OnDestroy()
{
    // register controls
    TUT_M_vGetTutDll();
    TUT_M_vUnregisterControlID( CPA_IDC_NEWMODEL  );
    TUT_M_vUnregisterControlID( CPA_IDC_DELMODEL  );
    TUT_M_vUnregisterControlID( CPA_IDC_SAVELIST  );
    TUT_M_vUnregisterControlID( CPA_IDC_LOADLIST  );
    TUT_M_vUnregisterControlID( CPA_IDC_COMBOTYPE );
    //
    CFormView::OnDestroy();
}

/*----------------------------------------
----------------------------------------*/
void CPA_DialogInsert::OnSelchangeCombotype() 
{
	
	// find the type of object to insert
	m_cComboType.GetLBText(m_cComboType.GetCurSel(), m_csTypeInsert);

	// update the list of descriptors
	fn_vUpdateListModel();
}


/*----------------------------------------
----------------------------------------*/
void CPA_DialogInsert::OnNewModel() 
{
	CPA_ObjectDLLBase	*p_oDLLInterface = NULL;
	EDT_ModelsByType	*pListType;
	CPA_MainWorld		*pMainWorld;
	CMenu				oMenu;
	RECT				WindowPosition;
	long				lIndex = 0;
	int					px, py;

	// find the DLL interface corresponding to the choice in Combo Box
	pListType = GetInterface()->GetModelsWithTypeName(m_csTypeInsert);
	if (pListType)
		p_oDLLInterface = pListType->GetDLL();
	if ((m_csTypeInsert == "All Types")&&(m_lNbValidNew == 1))
		p_oDLLInterface = GetSingleDllForNew();

	if (p_oDLLInterface)
	{
		fn_vLoadNewModel(p_oDLLInterface);
		return;
	}

	if (m_lNbValidNew == 0)
		return;

	// init mode
	m_ePopupMode = E_pm_NewModel;
	// create popup menu	
	oMenu.CreatePopupMenu();
	// entries for DLLs
	pMainWorld = M_GetMainWorld();
	do 
	{
		p_oDLLInterface = pMainWorld->GetListOfObjectDLLBase()->FindElementFromIndex(lIndex);
		if ((p_oDLLInterface)&&(p_oDLLInterface->fn_bCanLoadNewModel(m_csTypeInsert)))
			oMenu.AppendMenu(MF_STRING, lIndex, p_oDLLInterface->GetName());
		lIndex++;
	}
	while (p_oDLLInterface);
	if (!oMenu.GetMenuItemCount())
		oMenu.AppendMenu(MF_STRING, lIndex, "No New Available");
	// get position
	m_cNewModel.GetWindowRect(&WindowPosition);
	px = WindowPosition.right;
	py = WindowPosition.top;
    // register the popup menu for the tutorial module
    TUT_M_vGetTutDll    ();
    TUT_M_vRegisterMenu (this -> m_hWnd , oMenu . m_hMenu , px , py);
	// display & track popup menu
	oMenu.TrackPopupMenu(TPM_RIGHTALIGN | TPM_LEFTBUTTON, px, py, this);
	// destroy menus
	oMenu.DestroyMenu();
}

/*----------------------------------------
----------------------------------------*/
void CPA_DialogInsert::OnDelModel (void)
{
	EDT_Model	*pModel;
	BOOL		bRes;
	
	// all types => cannot remove
	if (m_csTypeInsert == "All Types")
		return;
	// get current model
	pModel = GetInterface()->GetCurrentModel();
	// remove it from the list
	if (pModel)
		bRes = GetInterface()->fn_bRemoveAModel(pModel->m_csName, m_csTypeInsert);
	// update list
	if (bRes)
	{
		GetInterface()->SetCurrentModel(NULL);
		fn_vUpdateListModel();
		GetInterface()->fn_vUpdateAll(E_mc_UpdateDialog);
	}
}

/*----------------------------------------
----------------------------------------*/
void CPA_DialogInsert::OnModelIcon (void)
{
	EDT_Model	*pModel;
	CString		csBitmapName;
	BOOL		bRes = FALSE;
	
	// all types => cannot remove
	if (m_csTypeInsert == "All Types")
		return;
	// get current model
	pModel = GetInterface()->GetCurrentModel();
	// remove it from the list
	if (pModel && pModel->m_pObjectDLL)
	{
		// get name for new icon
		csBitmapName = pModel->m_pObjectDLL->fn_csChangeModelIcon(m_csTypeInsert, pModel->m_csName);
		// load new icon
		bRes = pModel->fn_bChangeBitmap(GetInterface(), csBitmapName);
	}

	// update list
	if (bRes)
	{
		EDT_ModelsByType	*pListType;

		// update model in local list
		pListType = GetInterface()->GetModelsWithTypeName(m_csTypeInsert);
		pListType->fn_vRemoveAModel(pModel);
		pListType->fn_vAddANewModel(pModel);
		// update model in global list
		GetInterface()->GetListAllModels()->fn_vRemoveAModel(pModel);
		GetInterface()->GetListAllModels()->fn_vAddANewModel(pModel);
		// update drawing
		fn_vUpdateListModel();
		GetInterface()->fn_vUpdateAll(E_mc_UpdateDialog);
	}
}

/*----------------------------------------
----------------------------------------*/
void CPA_DialogInsert::OnSaveList() 
{
	CPA_ObjectDLLBase	*p_oDLLInterface;
	EDT_ModelsByType	*pListType;

	// find the DLL interface corresponding to the choice in Combo Box
	pListType = GetInterface()->GetModelsWithTypeName(m_csTypeInsert);
	if (pListType)
		p_oDLLInterface = pListType->GetDLL();
	else
		return;

	// call the corresponding save function
	p_oDLLInterface->fn_vSaveListModels(pListType->GetTypeName(), &pListType->m_stListModels);
}


/*----------------------------------------
----------------------------------------*/
void CPA_DialogInsert::OnLoadList() 
{
	CPA_ObjectDLLBase	*p_oDLL;
	CPA_MainWorld		*pMainWorld;
	CMenu				oMenu;
	RECT				WindowPosition;
	long				lIndex = 0;
	int					px, py;

	if (m_lNbValidLoad == 0)
		return;
	
	if (m_lNbValidLoad == 1)
	{
		p_oDLL = GetSingleDllForLoad();
		fn_vLoadListModels(p_oDLL);
		return;
	}

	// init mode
	m_ePopupMode = E_pm_LoadList;
	// create popup menu	
	oMenu.CreatePopupMenu();
	// entries for DLLs
	pMainWorld = M_GetMainWorld();
	do 
	{
		p_oDLL = pMainWorld->GetListOfObjectDLLBase()->FindElementFromIndex(lIndex);
		if ((p_oDLL)&&(p_oDLL->fn_bCanLoadListModels()))
			oMenu.AppendMenu(MF_STRING, lIndex, p_oDLL->GetName());
		lIndex++;
	}
	while (p_oDLL);
	if (!oMenu.GetMenuItemCount())
		oMenu.AppendMenu(MF_STRING, lIndex, "No Load Available");
	// get position
	m_cLoadList.GetWindowRect(&WindowPosition);
	px = WindowPosition.right;
	py = WindowPosition.top;
    // register the popup menu for the tutorial module
    TUT_M_vGetTutDll    ();
    TUT_M_vRegisterMenu (this -> m_hWnd , oMenu . m_hMenu , px , py);
	// display & track popup menu
	oMenu.TrackPopupMenu(TPM_RIGHTALIGN | TPM_LEFTBUTTON, px, py, this);
	// destroy menus
	oMenu.DestroyMenu();
}


/*----------------------------------------
----------------------------------------*/
BOOL CPA_DialogInsert::OnCommand (WPARAM wParam, LPARAM lParam)
{
	CPA_ObjectDLLBase	*p_oDLL;
	CPA_MainWorld		*pMainWorld;
	long				lIndex = 0;

	// entries for DLLs
	pMainWorld = M_GetMainWorld();
	// command from a menu
	if (HIWORD(wParam) == 0) 
	{
		// get ID of menu item
		lIndex = LOWORD(wParam); 
		// get corresponding DLL
		p_oDLL = pMainWorld->GetListOfObjectDLLBase()->FindElementFromIndex(lIndex);
		// do corresponding action
		if (m_ePopupMode == E_pm_NewModel)
			fn_vLoadNewModel(p_oDLL);
		else if (m_ePopupMode == E_pm_LoadList)
			fn_vLoadListModels(p_oDLL);
		// update popup mode
		m_ePopupMode = E_pm_NoMode;
	}
	return CFormView::OnCommand(wParam, lParam);
}


/*----------------------------------------
----------------------------------------*/
void CPA_DialogInsert::OnSize(UINT nType, int cx, int cy)
{
	RECT AbsolutePosition, WindowPosition;
	int px, py, cwx, cwy, crx, cx1, cry;

	if (m_bInitialised)
	{
		GetWindowRect(&WindowPosition);
		GetDlgItem(CPA_IDC_POSINSERT)->GetWindowRect(&AbsolutePosition);

		// calculate relative position
		cwx = WindowPosition.right - WindowPosition.left;
		cwy = WindowPosition.bottom - WindowPosition.top;
		crx = AbsolutePosition.right - AbsolutePosition.left;
		cry = AbsolutePosition.bottom - AbsolutePosition.top;
		py = AbsolutePosition.top - WindowPosition.top;
		crx = (crx < cwx) ? crx : cwx - 10;
		cx1 = (crx < 40) ? 40 : crx - 20;
		px = (cwx - crx) / 2; 

		// move button "Del" and "New"
		m_cNewModel.MoveWindow(px, py, cx1/11, cry-2);
		m_cDelModel.MoveWindow(px + crx/11 , py, cx1/11, cry-2);
		m_cModelIcon.MoveWindow(px + 2*crx/11 , py, cx1/11, cry-2);
		// move Static and Combo
		GetDlgItem(CPA_IDC_TEXT)->MoveWindow(px + 7*crx/22, py+4, cx1/11, cry);
		m_cComboType.MoveWindow(px + 9*crx/22, py, 4*cx1/11, cry);
		// move buttons "Save" and "Load"
		m_cSaveList.MoveWindow(px + 9*crx/11, py, cx1/11, cry);
		m_cLoadList.MoveWindow(px + 10*crx/11, py, cx1/11, cry);

		// Move the list
		fn_vReinitListModel();
	}
	return;
}


#endif // ACTIVE_EDITOR
