#include "MTH.h"
#include "Acp_base.h"
#include "Cpa_std.h"
#include "HDL.h"
#include "POS.h"
#include "GMT.h"
#include "GEO.h"
#include "COL.h"
#include "GLI.h"
#include "PIC.h"

/*#ifdef __cplusplus
extern "C" 
{
#endif
  M_LoadExternGlobalDeclaration();
#ifdef __cplusplus
} // extern "C" 
#endif*/

#ifdef ACTIVE_EDITOR

static MTH2D_tdstVector g_stSouris2D;
static GLD_tdhDevice g_hDev = 0;
static GLD_tdhViewport g_hVp = 0;
#endif

/*
#ifdef PC
extern float gs_xConstantFor3dfxBugFloat;
#endif
*/

/*************************************************************************************/
/*  Calcul de la position 3d de la souris. Le point 3d calcule appartient a l'ecran. */
/*************************************************************************************/
#ifdef ACTIVE_EDITOR
// active editor only
void PIC_vMouse3DScreen ( GLD_tdhDevice hDev,
                         GLD_tdhViewport hVp,
                         GLI_tdst2DVertex *p_stInput ,
                         MTH3D_tdstVector *p_stOutput )
{
  GLI_tdstSpecificAttributesFor3D *p_stSpecAttrib3D;
  GLD_tdstViewportAttributes    stViewAttrib;
  GLD_tdstDeviceAttributes    stDevAttrib;
  MTH3D_tdstVector stTemp ;
  POS_tdstCompletePosition stMatrix, stInvMatrix ;
  GLI_tdstCamera *p_stCam;
  GLI_tdst2DVertex stTrans;
  MTH_tdxReal xScreen;
  
  if ( !GLD_bGetViewportAttributes( hDev, hVp, &stViewAttrib ) ) return;
  if ( !GLD_bGetDeviceAttributes( hDev, &stDevAttrib ) ) return;
  p_stSpecAttrib3D = (GLI_tdstSpecificAttributesFor3D *)stViewAttrib.p_vSpecificToXD;
  p_stCam = p_stSpecAttrib3D->p_stCam;
 
  switch(p_stCam->lCameraMode)
  {
  case GLI_C_lIsoCamWithDistorsion :
  case GLI_C_lIsoCamWithoutDistorsion :
    xScreen = MTH_M_xFloatToReal(0.1f);
    break;
  case GLI_C_lPersCamWithDistorsion :
  case GLI_C_lPersCamWithoutDistorsion :
    xScreen = p_stCam->xScreen;
    break ;
  default:
    p_stOutput->xX = p_stOutput->xY = p_stOutput->xZ = MTH_M_xFloatToReal(0.0f);
    return;
  }
  
  /* on se ramene en unite du monde */
/*
  if(GLI_lWhatIsGLI() == GLI_C_VersionGlide)
  {
#ifdef PC
    stTrans.xX = p_stCam->stTrans.xX - gs_xConstantFor3dfxBugFloat;
    stTrans.xY = p_stCam->stTrans.xY - gs_xConstantFor3dfxBugFloat;
#endif
  }
  else
  {
    stTrans.xX = p_stCam->stTrans.xX;
    stTrans.xY = p_stCam->stTrans.xY;
  }
  */
  stTrans.xX = p_stCam->stTrans.xX;
  stTrans.xY = p_stCam->stTrans.xY;
  
  stTemp.xX = MTH_M_xDiv( MTH_M_xSub( MTH_M_xLongToReal(p_stInput->xX), MTH_M_xLongToReal(stTrans.xX)),
    MTH_M_xFloatToReal(p_stCam->stScale.xX));
  stTemp.xY = MTH_M_xDiv( MTH_M_xSub( MTH_M_xLongToReal(p_stInput->xY), MTH_M_xLongToReal(stTrans.xY) ),
    MTH_M_xFloatToReal(p_stCam->stScale.xY) ) ;
  stTemp.xZ = xScreen;
  
  /*    Convertion dans le repere du monde */
  GLI_xGetCameraMatrix ( p_stCam , &stMatrix );
  POS_fn_vInvertMatrix( &stInvMatrix , &stMatrix );  
  POS_fn_vMulMatrixVertex( p_stOutput , &stInvMatrix , &stTemp );    
}
#endif


#ifdef ACTIVE_EDITOR
// active editor only
void PIC_vGetPosCamAndMouse(GLD_tdhDevice hDev,
                            GLD_tdhViewport hVp,
                            GLI_tdst2DVertex *p_stSouris2D,
                            MTH3D_tdstVector *p_stSouris3D,
                            MTH3D_tdstVector *p_stCamera)
{
  GLD_tdstViewportAttributes stViewAttrib;
  GLI_tdstSpecificAttributesFor3D *p_stSpecAttrib3D;
  GLI_tdstCamera *p_stCam;
  POS_tdstCompletePosition stMatrix, stInvMatrix;
  MTH3D_tdstVector stAxe, stAxeZ;
  MTH3D_tdstVector stSouris3D, stTmp;
  MTH3D_tdstVector stTrans;
  
  // recuperation de la camera
  if(!GLD_bGetViewportAttributes(hDev, hVp, &stViewAttrib))  return;
  p_stSpecAttrib3D = (GLI_tdstSpecificAttributesFor3D *)stViewAttrib.p_vSpecificToXD;
  p_stCam = p_stSpecAttrib3D->p_stCam;
  
  PIC_vMouse3DScreen ( hDev, hVp, p_stSouris2D , &stSouris3D );

  // get camera position
  if(  p_stCam->lCameraMode == GLI_C_lPersCamWithDistorsion 
    || p_stCam->lCameraMode == GLI_C_lPersCamWithoutDistorsion )
  {
    GLI_xGetCameraMatrix ( p_stCam, &stMatrix );
    POS_fn_vInvertMatrix( &stInvMatrix , &stMatrix );  
    POS_fn_vGetTranslationVector( &stInvMatrix , p_stCamera );
  }
  else if(  p_stCam->lCameraMode == GLI_C_lIsoCamWithDistorsion 
    || p_stCam->lCameraMode == GLI_C_lIsoCamWithoutDistorsion )
  {
    // calcul de l'axe Z de la camera
    GLI_xGetCameraMatrix ( p_stCam, &stMatrix );
    POS_fn_vInvertMatrix( &stInvMatrix , &stMatrix );  
    stAxe.xX = MTH_M_xFloatToReal(0.0);
    stAxe.xY = MTH_M_xFloatToReal(0.0);
    stAxe.xZ = MTH_M_xFloatToReal(1.0);
    POS_fn_vMulMatrixVertex(&stTmp, &stInvMatrix, &stAxe);
    POS_fn_vGetTranslationVector( &stInvMatrix,&stTrans);
    MTH3D_M_vSubVector(&stAxeZ, &stTmp, &stTrans);
    MTH3D_M_vSubVector(p_stCamera, &stSouris3D, &stAxeZ);
  }
  
  if(p_stSouris3D != NULL)
  {
    *p_stSouris3D = stSouris3D;
  }
  
  g_stSouris2D.xX = p_stSouris2D->xX;
  g_stSouris2D.xY = p_stSouris2D->xY;
  g_hDev = hDev;
  g_hVp = hVp;
}
#endif 


#ifdef ACTIVE_EDITOR
// active editor only
BOOL PIC_xIntersectSemiAxeWithSphereBox(MTH3D_tdstVector *p_stVertexA,
                                        MTH3D_tdstVector *p_stVectAB,
                                        GLI_tdstSphere *p_stSphere )
{
  return TRUE;
}

#endif

// used

BOOL PIC_bIntersectSegmentWithGeometricObject(MTH3D_tdstVector *p_stCameraPos,
                                              MTH3D_tdstVector *p_stVertex12, 
                                              GEO_tdstGeometricObject *p_stObject ,
                                              PIC_tdstPickedObject *p_stPickedObject)
{
//	GLI_tdstSphere stSphere;
	ACP_tdxIndex xNbElements;
	BOOL bTest,bReturn = FALSE;
	MTH3D_tdstVector stSouris3D;
	
	MTH3D_M_vAddVector(&stSouris3D, p_stCameraPos, p_stVertex12);
	
    bTest = INT_fn_bIntersectSegmentWithFaceOfGeometricObject(p_stCameraPos,
		&stSouris3D,
		p_stVertex12,
		p_stObject,
		PIC_C_DepthPickingElements,
		&xNbElements,
		p_stPickedObject->aDEF_stDataOfElement);
    
    if( bTest ) 
    {
		MTH3D_tdstVector stTemp;
		ACP_tdxIndex i;
		
		POS_fn_vMulMatrixVertex(&stTemp, g_p_stCurrentMatrix, p_stCameraPos);
		
		for(i=0; i<xNbElements; i++)
		{
			POS_fn_vMulMatrixVertex(&(p_stPickedObject->aDEF_stDataOfElement[i].stHit),
				g_p_stCurrentMatrix,
				&(p_stPickedObject->aDEF_stDataOfElement[i].stHit));
			
			p_stPickedObject->aDEF_stDataOfElement[i].xDistance = 
				MTH3D_M_xVectorGap(&stTemp, &(p_stPickedObject->aDEF_stDataOfElement[i].stHit));
		}
		p_stPickedObject->xNbElements = xNbElements;
		p_stPickedObject->xModePicking = PIC_C_ModePickingFace;
		
		bReturn = TRUE;
    }
	
	return bReturn;
}


#if defined(ACTIVE_EDITOR)			
// active editor only
BOOL PIC_bIntersectSemiAxeWithGeometricObject(PIC_tdeModePicking xModePicking,
                                              MTH3D_tdstVector *p_stCameraPos,
                                              MTH3D_tdstVector *p_stVertex12, 
                                              GEO_tdstGeometricObject *p_stObject ,
                                              PIC_tdstPickedObject *p_stPickedObject)
{
	GLI_tdstSphere stSphere;
	ACP_tdxIndex xNbElements;
	//XB980505
	//  BOOL bTest,bReturn = FALSE;
	BOOL bTest=FALSE;
	BOOL bReturn = FALSE;
	//End XB
	MTH3D_tdstVector stSouris3D;
	GLI_tdst2DVertex stInput;
	MTH3D_tdstVector stOutput;
	POS_tdstCompletePosition stInvMatrix;
	
	//  stSphere = p_stObject->stAbsoluteSphereBox;
	
	MTH3D_M_vAddVector(&stSouris3D, p_stCameraPos, p_stVertex12);
	
	if(PIC_xIntersectSemiAxeWithSphereBox(p_stCameraPos, p_stVertex12, &stSphere) )
	{
		switch(xModePicking)
		{
			
		case PIC_C_ModePickingFace:
			bTest = INT_fn_bIntersectSemiAxeWithFaceOfGeometricObject(p_stCameraPos,
				&stSouris3D,
				p_stVertex12,
				p_stObject,
				PIC_C_DepthPickingElements,
				&xNbElements,
				p_stPickedObject->aDEF_stDataOfElement);
			if(GLD_bIsDeviceHandleValid(g_hDev) && GLD_bIsViewportHandleValid(g_hVp))
			{
				stInput.xX = g_stSouris2D.xX;
				stInput.xY = g_stSouris2D.xY;
				PIC_vMouse3DScreen(g_hDev, g_hVp, &stInput, &stOutput);
				POS_fn_vInvertMatrix(&stInvMatrix , g_p_stCurrentMatrix);
				POS_fn_vMulMatrixVertex(&stOutput, &stInvMatrix, &stOutput);
				if( MTH3D_M_bEqualVector(&stOutput, &stSouris3D) )
				{
					GLD_tdstViewportAttributes stViewAttrib;
					
					if ( !GLD_bGetViewportAttributes( g_hDev, g_hVp, &stViewAttrib ) ) return FALSE;
					bTest += GLI_lPickSprites ( &stViewAttrib,
						p_stObject,
						&g_stSouris2D,
						PIC_C_DepthPickingElements,
						&xNbElements,
						p_stPickedObject->aDEF_stDataOfElement,
						p_stCameraPos,
						FALSE);
				}
			}
			break;
			
		case PIC_C_ModePickingEdge:
			bTest = INT_fn_bIntersectSemiAxeWithEdgeOfGeometricObject(p_stCameraPos,
				p_stVertex12,
				p_stObject,
				PIC_C_DepthPickingElements,
				&xNbElements,
				p_stPickedObject->aDEF_stDataOfElement);
			break;
			
		case PIC_C_ModePickingPoint:
			bTest = INT_fn_bIntersectSemiAxeWithPointOfGeometricObject(p_stCameraPos,
				p_stVertex12,
				p_stObject,
				PIC_C_DepthPickingElements,
				&xNbElements,
				p_stPickedObject->aDEF_stDataOfElement);
			break;
		}
		
		if( bTest ) // l'objet est sous la souris
		{
			MTH3D_tdstVector stTemp;
			ACP_tdxIndex i;
			
			POS_fn_vMulMatrixVertex(&stTemp, g_p_stCurrentMatrix, p_stCameraPos);
			
			for(i=0; i<xNbElements; i++)
			{
				
				POS_fn_vMulMatrixVertex(&(p_stPickedObject->aDEF_stDataOfElement[i].stHit),
					g_p_stCurrentMatrix,
					&(p_stPickedObject->aDEF_stDataOfElement[i].stHit));
				
				switch(xModePicking)
				{
				case PIC_C_ModePickingFace:
					p_stPickedObject->aDEF_stDataOfElement[i].xDistance = 
						MTH3D_M_xVectorGap(&stTemp, &(p_stPickedObject->aDEF_stDataOfElement[i].stHit));
					break;
					
				case PIC_C_ModePickingEdge:
					p_stPickedObject->aDEF_stDataOfElement[i].xDistance = 
						MTH3D_M_xVectorGap(&(p_stPickedObject->aDEF_stDataOfElement[i].stHit),
						p_stObject->d_stListOfPoints + p_stPickedObject->aDEF_stDataOfElement[i].xIndexOfEdge);
					break;
					
				case PIC_C_ModePickingPoint:
					p_stPickedObject->aDEF_stDataOfElement[i].xDistance = 
						MTH3D_M_xVectorGap(&(p_stPickedObject->aDEF_stDataOfElement[i].stHit),
						p_stObject->d_stListOfPoints + p_stPickedObject->aDEF_stDataOfElement[i].xIndexOfPoint);
					break;
				}
			}
			p_stPickedObject->xNbElements = xNbElements;
			p_stPickedObject->xModePicking = xModePicking;
			
			bReturn = TRUE;
		}
	}
	
	return bReturn;
}
#endif // ACTIVE_EDITOR

