------ All content © 2008 DigiPen (USA) Corporation, all rights reserved. ------
-- Updated: 11/14/2008

dofile( "../../Assets/Scripts/key_name_mappings.lua" )
dofile( "../../Assets/Scripts/util_math.lua" )

--------------------------------------------------------------------------------
-- Fuctions!
-- This might look redundant, but avoids costly global lookup
--------------------------------------------------------------------------------
local ENTITY = Entity

local ENTITY_SHR_Refresh             = Entity.SHR_Refresh
local ENTITY_SPT_RefreshNumbers      = Entity.SPT_RefreshNumbers

local GLOBAL_GameModeCAMERA          = Global.GameModeCAMERA
local GLOBAL_gRangeState             = Global.gRangeState
local GLOBAL_IsInGameMode            = Global.IsInGameMode
local GLOBAL_IsGameButtonTriggered   = Global.IsGameButtonTriggered
local GLOBAL_IsGameButtonPressed     = Global.IsGameButtonPressed
local GLOBAL_UpdateCameraThird       = Global.UpdateCameraThird
local GLOBAL_SetRepulseState         = Global.SetRepulseState
local GLOBAL_SetCameraViewVector     = Global.SetCameraViewVector
local GLOBAL_gCameraBasis            = Global.gCameraBasis

local VEC3_add                       = vec3.add
local VEC3_addThis                   = vec3.addThis
local VEC3_normalize                 = vec3.normalize
local VEC3_multiplyThis              = vec3.multiplyThis
local VEC3_subtractThis              = vec3.subtractThis
local VEC3_multiply                  = vec3.multiply
local VEC3_toSpherical               = vec3.toSpherical

--==============================================================================

local FORWARD
local SIDE
local UP
local GAMEMODECAMERA = GLOBAL_GameModeCAMERA()
local UpdateCamera
local myData = {}
local defaultDist = 12
myData.ThetaSpeed = 0
myData.PhiSpeed   = 0
local LAZYTIME = 60
local lazyTime = LAZYTIME

local function addNegInvSecond( v, indx, forward, side, up )
  if( indx <= 6 )
  then
    v = VEC3_add(v, VEC3_multiply(side, 1 / checkPts[indx].x))
  elseif( indx <= 12 )
  then
    v = VEC3_add(v, VEC3_multiply(up, 1 / checkPts[indx].y))
  else
    v = VEC3_add(v, VEC3_multiply(forward, -1 / checkPts[indx].z))
  end
  return v
end

local function WithOrient( update )
  lazyTime = lazyTime - 1
  if( Approx(update.x, 0) and Approx(update.z, 0) and Approx(update.zoom, 1) )
  then --user isn't changing camera so we should try and swing it behind
    if( lazyTime < 0 )
    then
      GLOBAL_SetRepulseState( true )
      ENTITY_SPT_RefreshNumbers( ENTITY, myData )
      if( myData.ThetaSpeed ~= 0 or myData.PhiSpeed ~= 0 )
      then
        local tempX = myData.x
        local tempY = myData.y
        local tempZ = myData.z
        myData.x =     SIDE.x * tempX +    SIDE.y * tempY +    SIDE.z * tempZ
        myData.y =       UP.x * tempX +      UP.y * tempY +      UP.z * tempZ
        myData.z = -FORWARD.x * tempX - FORWARD.y * tempY - FORWARD.z * tempZ
        VEC3_toSpherical( myData )
        local viewVec = Global:gCameraViewVector()
        viewVec = VEC3_normalize( viewVec )
        tempX = viewVec.x
        tempY = viewVec.y
        tempZ = viewVec.z
        viewVec.x =     SIDE.x * tempX +    SIDE.y * tempY +    SIDE.z * tempZ
        viewVec.y =       UP.x * tempX +      UP.y * tempY +      UP.z * tempZ
        viewVec.z = -FORWARD.x * tempX - FORWARD.y * tempY - FORWARD.z * tempZ
        VEC3_toSpherical( viewVec )

        --theta
        local dTheta = viewVec.theta - myData.theta
        if( dTheta > PI )
        then
          dTheta = dTheta - TWO_PI
        elseif( dTheta < -PI )
        then
          dTheta = TWO_PI + dTheta
        end
        dTheta = dTheta * myData.ThetaSpeed

        --phi
        local dPhi = myData.phi - viewVec.phi
        dPhi = dPhi * myData.PhiSpeed

		if( math.abs(dTheta) > myData.FollowThreshold or math.abs(dPhi) > myData.FollowThreshold )
		then
          GLOBAL_UpdateCameraThird(dTheta, dPhi, 1)
        end
      end
    end
  else --the user is moving the camera, so don't mess with it
    lazyTime = LAZYTIME
    GLOBAL_SetRepulseState( false )
    GLOBAL_UpdateCameraThird(update.x * myData.Xinv, update.z * myData.Yinv, update.zoom)
  end
end

local function WithoutOrient( update )
  GLOBAL_UpdateCameraThird(update.x * myData.Xinv, update.z * myData.Yinv, update.zoom)
end


ENTITY_SPT_RefreshNumbers( ENTITY, myData )
if( myData.Orient ~= 0 )
then
  UpdateCamera = WithOrient
else
  UpdateCamera = WithoutOrient
end

myData.Xinv = 1
myData.Yinv = 1

while( 1 ) 
do
  coroutine.yield()

  ENTITY = Entity

  ENTITY_SHR_Refresh( ENTITY, myData, true, false, false, false )
  ENTITY_SPT_RefreshNumbers( ENTITY, myData )
  
  if( GLOBAL_IsInGameMode() >= GAMEMODECAMERA )
  then
    FORWARD, SIDE, UP = GLOBAL_gCameraBasis()
    local range = GLOBAL_gRangeState(1)

    range.zoom = 1
    --Dev debug zoom controls
	--[[ --]]
	if GLOBAL_IsGameButtonPressed( 6 ) -- button 7
    then
      range.zoom = 1.05
    elseif GLOBAL_IsGameButtonPressed( 5 ) -- button 6
    then
      range.zoom = .95
    end
    

    if( GLOBAL_IsGameButtonTriggered( 3 ) or myData.centerCamera == 1 ) -- button 4
    then
      lazyTime = 0
      myData.centerCamera = 0
      ENTITY_SPT_RefreshNumbers( ENTITY, myData )
      local projOnUp = vec3.dot(myData, UP)
      VEC3_subtractThis(myData, VEC3_multiply(UP, projOnUp))
      projOnUp = -.8 * projOnUp
      VEC3_addThis(myData, VEC3_multiply(UP, projOnUp))
      VEC3_normalize( myData )
      VEC3_multiplyThis( myData, defaultDist )
      GLOBAL_SetCameraViewVector(myData.x, myData.y, myData.z)
    else
      UpdateCamera( range )
    end
  
  end

end
