/*************************************************************************
Crytek Source File.
Copyright (C), Crytek Studios, 2001-2004.
-------------------------------------------------------------------------
$Id$
$DateTime$

-------------------------------------------------------------------------
History:
- 09:01:2006   14:00 : Created by Michael Rauh

*************************************************************************/
#include "StdAfx.h"
#include "DebugGun.h"

#include <IActorSystem.h>
#include <IVehicleSystem.h>
#include <IMovementController.h>
#include "Actor.h"
#include "Game.h"

#define HIT_RANGE (2000.0f)

//------------------------------------------------------------------------
CDebugGun::CDebugGun()
{  
  m_pAIDebugDraw = GetISystem()->GetIConsole()->GetCVar("ai_debugdraw");
  m_aiDebugDrawPrev = m_pAIDebugDraw->GetIVal();
  m_fireMode = 0;
  
  for (int i=15; i>=0; --i)
  { 
    m_fireModes.push_back(TFmPair("pierceability", (float)i));
  }
}

//------------------------------------------------------------------------
void CDebugGun::OnAction(EntityId actorId, const char *actionName, int activationMode, float value)
{
  if (!strcmp(actionName, "attack1"))  
  {     
    if (activationMode == eAAM_OnPress)
      Shoot(actorId, true);    
  }
  else if (!strcmp(actionName, "zoom"))
  {
    if (activationMode == eAAM_OnPress)
      Shoot(actorId, false);
  }  
  else if (!strcmp(actionName, "firemode"))
  {
    ++m_fireMode;

    if (m_fireMode == m_fireModes.size())
      m_fireMode = 0;
    
    //SGameObjectEvent evt("HUD_TextMessage", eGOEF_ToAll, IGameObjectSystem::InvalidExtensionID, (void*)m_fireModes[m_fireMode].c_str());
    //GetISystem()->GetIGame()->GetIGameFramework()->GetIGameObjectSystem()->BroadcastEvent(evt);
  }
  else
    CWeapon::OnAction(actorId, actionName, activationMode, value);
}

//------------------------------------------------------------------------
void CDebugGun::Update( SEntityUpdateContext& ctx, int update)
{
  static const unsigned int objTypes = ent_all;    
  static IPhysicalWorld* pWorld = GetISystem()->GetIPhysicalWorld();  
  static IMaterialManager* pMatMan = GetISystem()->GetI3DEngine()->GetMaterialManager();
  
  static IRenderer* pRenderer = GetISystem()->GetIRenderer();
  static float drawColor[4] = {1,1,1,1};
  static int dx = 5; 
  static int dy = 15;

  pRenderer->Draw2dLabel(pRenderer->GetWidth()/5.f, pRenderer->GetHeight()-35, 1.4f, drawColor, false, "Firemode: %s (%.1f)", m_fireModes[m_fireMode].first.c_str(), m_fireModes[m_fireMode].second);      

  ray_hit rayhit;
  int hits = 0;
  
  int flags = rwi_stop_at_pierceable|rwi_colltype_any|rwi_any_hit;
  if (m_fireModes[m_fireMode].first == "pierceability")
  { 
    flags = (int)m_fireModes[m_fireMode].second & rwi_pierceability_mask;
  }
  
  // use cam, no need for firing pos/dir
  CCamera& cam = GetISystem()->GetViewCamera();

  if (hits = pWorld->RayWorldIntersection(cam.GetPosition()+cam.GetViewdir(), cam.GetViewdir()*HIT_RANGE, objTypes, flags, &rayhit, 1))
  {
    int x = (int)(pRenderer->GetWidth() *0.5f) + dx;
    int y = (int)(pRenderer->GetHeight()*0.5f) + dx - dy;

    IEntity * pEntity = (IEntity*)rayhit.pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY);
    if(pEntity)
    {  
      pRenderer->Draw2dLabel(x, y+=dy, 1.4f, drawColor, false, pEntity->GetName());      
    }
    
    const char* matName = pMatMan->GetSurfaceType(rayhit.surface_idx)->GetName();

    if (matName[0])      
      pRenderer->Draw2dLabel(x, y+=dy, 1.2f, drawColor, false, "%s (%i)", matName, rayhit.surface_idx);
  }  
}

//------------------------------------------------------------------------
void CDebugGun::Shoot(EntityId shooterId, bool bPrimary)
{   
  CWeapon::StartFire(shooterId);

  ResetAnimation();
  
  // console cmd      
  string cmd;  
  static ICVar* pCmd1 = GetISystem()->GetIConsole()->GetCVar("i_debuggun_1");
  static ICVar* pCmd2 = GetISystem()->GetIConsole()->GetCVar("i_debuggun_2");

  cmd = (bPrimary) ? pCmd1->GetString() : pCmd2->GetString();  
  cmd += " ";        
  
  static const unsigned int objTypes = ent_all;    
  static const int flags = rwi_stop_at_pierceable|rwi_colltype_any|rwi_any_hit;                      
  
  IPhysicalWorld* pWorld = GetISystem()->GetIPhysicalWorld();
  IPhysicalEntity *pSkip = GetOwnerActor()->GetEntity()->GetPhysics();
  ray_hit rayhit;
  int hits = 0;

  CCamera& cam = GetISystem()->GetViewCamera();
  Vec3 pos = cam.GetPosition()+cam.GetViewdir();
  Vec3 dir = cam.GetViewdir() * HIT_RANGE;

  IEntity* pEntity = 0;

  if (hits = pWorld->RayWorldIntersection(pos, dir, objTypes, flags, &rayhit, 1, &pSkip, 1))
  {
    pEntity = (IEntity*)rayhit.pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY);        
  }
  
  cmd.append(pEntity ? pEntity->GetName() : "\"\"");   
  
  // if we execute an AI command take care of ai_debugdraw
  if (cmd.substr(0, 3) == "ai_")
  {
    if (pEntity && m_pAIDebugDraw->GetIVal() == 0)
      m_pAIDebugDraw->Set(1);
    else if(!pEntity && m_aiDebugDrawPrev == 0 && m_pAIDebugDraw->GetIVal() == 1)
      m_pAIDebugDraw->Set(0);
  }

  GetISystem()->GetIConsole()->ExecuteString(cmd.c_str());

  // if 2nd button hits a vehicle, enable movement profiling  
  if (!bPrimary)
  {
    static IVehicleSystem* pVehicleSystem = g_pGame->GetIGameFramework()->GetIVehicleSystem();
     
    string vehicleCmd = "v_debugVehicle ";
    vehicleCmd.append((pEntity && pVehicleSystem->GetVehicle(pEntity->GetId())) ? pEntity->GetName() : "\"\"");
    
    GetISystem()->GetIConsole()->ExecuteString(vehicleCmd.c_str());
  }

  OnShoot(shooterId, 0, "", pos, dir, Vec3(ZERO));
    
}

//------------------------------------------------------------------------
void CDebugGun::Select(bool select)
{
  CWeapon::Select(select);

  // save ai_debugDraw val
  if (select)
    m_aiDebugDrawPrev = m_pAIDebugDraw->GetIVal();
}

