-------------------------------------------------------------------------------
-- ****************************************************************************
--  Entity: Final Boss
--  Phase: 1 of 3
--  State: Global
-- ****************************************************************************
-------------------------------------------------------------------------------

--[[
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/////                              Variables                              /////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
--]]

-- Define the table that will contain the state
MegaWhiteShark_Phase1_Global = {}

-- Name of state
local STATE_NAME = "MegaWhiteShark_Phase1_Global"
registerStateFSM( STATE_NAME )  -- do NOT touch this!!


--[[
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/////                               Functions                             /////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
--]]

--[[---------------------------------------------------------------------------
  isTrapped
-------------------------------------------------------------------------------
  Description: 
    - determines if the current entity is in the Vulnerable state.
  Return:
    - true if entity is in the Vulnerable state
    - false otherwise
  Params:
    - entity: the pointer to the entity
-----------------------------------------------------------------------------]]
local function isTrapped( entity )
  
  local current_state_name = getCurrentStateName( entity:ID() )
  
  -- if the current state name is equal to the Vulnerable state name
  -- return true
  if( current_state_name == "MegaWhiteShark_Phase1_Vulnerable" ) then
    return true
  end
  
  -- otherwise, return false
  return false
end


--[[---------------------------------------------------------------------------
  isIdle
-------------------------------------------------------------------------------
  Description: 
    - determines if the current entity is in the Idle state.
  Return:
    - true if entity is in the Idle state
    - false otherwise
  Params:
    - entity: the pointer to the entity
-----------------------------------------------------------------------------]]
local function isIdle( entity )
  
  local current_state_name = getCurrentStateName( entity:ID() )
  
  -- if the current state name is equal to the Vulnerable state name
  -- return true
  if( current_state_name == "MegaWhiteShark_Phase1_Idle" ) then
    return true
  end
  
  -- otherwise, return false
  return false
end


--[[---------------------------------------------------------------------------
  isRunning
-------------------------------------------------------------------------------
  Description: 
    - determines if the current entity is in the RunToPlayer state.
  Return:
    - true if entity is in the RunToPlayer state
    - false otherwise
  Params:
    - entity: the pointer to the entity
-----------------------------------------------------------------------------]]
local function isRunning( entity )
  
  local current_state_name = getCurrentStateName( entity:ID() )
  
  -- if the current state name is equal to the Vulnerable state name
  -- return true
  if( current_state_name == "MegaWhiteShark_Phase1_RunToPlayer" ) then
    return true
  end
  
  -- otherwise, return false
  return false
end


--[[---------------------------------------------------------------------------
  isHitFromBack
-------------------------------------------------------------------------------
  Description: 
    - determines if the current entity has been hit from back or not
  Return:
    - true if entity is hit from back
    - false otherwise
  Params:
    - entity: the pointer to the entity
    - message: the message that contains extra information
  NOTE:
    - here we are assuming that the entity can ONLY be hit by the player
      which is exactly what happens in the game because the final boss can only
      receive damage from the player, but in a more complex scenario we should
      get the "attacking entity position" from the message extraInfo parameters
-----------------------------------------------------------------------------]]
local function isHitFromBack( entity, message )

  -- get the necessary vectors to make the dot_product calculation
  local entity_pos = entity:getPosition()
  local player_pos = getPlayerPosition()
  local entity_front = entity:getFront()
  
  local entity_to_player = player_pos - entity_pos
  local dot_product = vector3Dot( entity_front, entity_to_player )
  
  -- if the dot product is Negative, it means the entity was hit from it's back
  if( dot_product < 0.0 ) then
    return true
  end
  
  -- otherwise, return false
  return false
end


--[[---------------------------------------------------------------------------
  processHitMessage
-------------------------------------------------------------------------------
  Description: 
    - determines how to handle a Hit Message and if it does damage to the
      Entity or it does not.
  Return:
    - true if message has been processed
    - false otherwise
  Params:
    - entity: the pointer to the entity who receives the message
    - message: the message itself
-----------------------------------------------------------------------------]]
local function processHitMessage( entity, message )

  -- if message sent by himself, mark it as processed and return true
  if ( message.Sender == message.Receiver ) then
    return true
  end
  
  -- if message sent by his weapon, mark it as processed and return true
  local sword_id = getExtraItemID( 0, entity:ID() )
  local shield_id = getExtraItemID( 1, entity:ID() )
  if( message.Sender == sword_id ) then
    return true
  end
  
  if( message.Sender == shield_id ) then
    return true
  end
  
  -- otherwise, process the message
  local is_vulnerable = isTrapped( entity )
  local is_hit_from_back = isHitFromBack( entity, message )
  local is_idle = isIdle( entity )
  local is_running = isRunning( entity )
  
  -- If Not vulnerable and Not hit from back: Block the attack
  if( not ( is_hit_from_back ) ) then
    changeEntityState( entity:ID(), "MegaWhiteShark_Phase1_Block" )  
    return true
    
  -- If Vulnerable AND HitFromBack: Receive the hit
  elseif( is_vulnerable and is_hit_from_back ) then
    changeEntityState( entity:ID(), "MegaWhiteShark_Phase1_ReceiveHit" )
    return true
    
  -- If HitFromBack and is in state running OR idle: Receive the hit
  elseif( is_hit_from_back and ( is_idle or is_running ) )then
    changeEntityState( entity:ID(), "MegaWhiteShark_Phase1_ReceiveHit" )
    return true
  end
  
  -- otherwise, message has not been processed and we must return false
  return false
end


--[[---------------------------------------------------------------------------
  processRigidPushMessage
-------------------------------------------------------------------------------
  Description: 
    - ...
  Return:
    - true if message has been processed
    - false otherwise
  Params:
    - entity: the pointer to the entity who receives the message
    - message: the message itself
-----------------------------------------------------------------------------]]
local function processRigidPushMessage( entity, message )

  local info_push_normal = getInfoPushNormal( message )    
  correctEntityPosition( entity:ID(), info_push_normal ) -- * 0.5 )
  return true	  
end


--[[---------------------------------------------------------------------------
  processModifySpeedMessage
-------------------------------------------------------------------------------
  Description: 
    - ...
  Return:
    - true if message has been processed
    - false otherwise
  Params:
    - entity: the pointer to the entity who receives the message
    - message: the message itself
-----------------------------------------------------------------------------]]
local function processModifySpeedMessage( entity, message )

  modifySpeed( entity:ID(), message )
  return true
end


--[[---------------------------------------------------------------------------
  processPutOnPlatformMessage
-------------------------------------------------------------------------------
  Description: 
    - ...
  Return:
    - true if message has been processed
    - false otherwise
  Params:
    - entity: the pointer to the entity who receives the message
    - message: the message itself
-----------------------------------------------------------------------------]]
local function processPutOnPlatformMessage( entity, message )
  
  putEntityOnPlatform( entity:ID(), message )
  return true
end

--[[
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/////                               States                                /////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
--]]

-------------------------------------------------------------------------------
-- Execute
-------------------------------------------------------------------------------
MegaWhiteShark_Phase1_Global["Execute"] = function(entity)

end

-------------------------------------------------------------------------------
-- OnMessage
-------------------------------------------------------------------------------
MegaWhiteShark_Phase1_Global["OnMessage"] = function(entity, message)

  -- Receive Hit
  if ( message.Msg == Telegram.Receive_Hit ) then
    return processHitMessage( entity, message )
  
  -- Rigid Push Interactive
  elseif( message.Msg == Telegram.Rigid_Push_Interactive ) then
    return processRigidPushMessage( entity, message )
    
  -- Modify Speed
  elseif( message.Msg == Telegram.Modify_Speed ) then
    return processModifySpeedMessage( entity, message )
  
  -- Put On Platform
  elseif( message.Msg == Telegram.Put_On_Platform ) then
    return processPutOnPlatformMessage( entity, message )
    
  elseif ( message.Msg == Telegram.Init_States_Phase1 ) then
    changeEntityState( entity:ID(), "MegaWhiteShark_Phase1_Init" )
    return true
    
  else
    local message_id = message.Msg
    local message_not_processed = true
  end

--[[
  // Cuando el player es empujado por otro objeto
  // recibe: la normal y renueva la posición
  else if ( msg.Msg == Msg_Rigid_Push_Interactive ) {


  }

  else if( msg.Msg == Msg_Interactive_Clear_Speed ){
	  pShark->setSpeed( 0.0f );
	  return true;
  }

  else if( msg.Msg == Msg_Modify_Speed ){

	  CollisionInfo collInfo = (*(CollisionInfo*) msg.ExtraInfo);
	  D3DXVECTOR3 normal = -collInfo.normalCollision;
	  D3DXVECTOR3 relativeDirection = collInfo.relativeDirection;
	  float relativeSpeed = collInfo.relativeSpeed;

	  D3DXVec3Normalize( &normal, &normal );

	  float vn = D3DXVec3Dot( &normal, &relativeDirection );
	  float elasticityFactor = 0;

	  if( vn < 0){
		  pShark->setDirection( relativeDirection - ( ( 1 + elasticityFactor ) * vn * normal ));
	  }

	   pShark->Colision_normal = pShark->getDirection() * 10;
  }

  else if ( msg.Msg == Msg_Put_On_Platform )
  {
	  float y_Position = (*(float*) msg.ExtraInfo);
	  pShark->setCurrentCollisionPlane( y_Position );
    return true;
  }

   else if ( msg.Msg == Msg_Actor_DisableComicDialog ){
    pShark->setRepresentationComicDialogVisible( false );
  }
]]--

  -- if message NOT handled, return false
  return false
end

-------------------------------------------------------------------------------
-- GetNameOfCurrentState
-------------------------------------------------------------------------------
MegaWhiteShark_Phase1_Global["GetNameOfCurrentState"] = function()
  
  return STATE_NAME
end
