if not FSM_LUA   then dofile("fsm.lua")   end
if not TRACK_LUA then dofile("track.lua") end
AI_LUA = true

-- define AI states here:
STATE_AI_FOLLOWWP   = "WAYPOINTS"  -- ai is just going from one wp to next
STATE_AI_AGGRESSIVE = "AGGRESSIVE" -- ai speeds towards the player


ai = FSM:instantiate { state = STATE_NONE; tostr = "AI_FSM"; smooth = 8 }

--  new AIs should be instantiated with the "mobile" field set as follows:
--  some_mobile.newai = ai:instantiate{mobile = some_mobile}
--  this will insure that the ai has access to the mobile it is trying to
--  control.

--  AI's also have access to the member functions of the FSM class.
--  To change an AI's state use self:set_state(NEW_STATE)
--  To respond to state changes use self:do_change_state(prev_state, new_state)

--  see main.lua do_start() for initial creation of AI's

--  AIs should use the following values to query the mobile:
--  in self.mobile:
--     px, py, pz : position in x, y, z
--     rx, ry, rz : rotation of mobile in radians
--     sx, sy, sz : spin (or angular velocity) in radians per sec
--     tx, ty, tz : angular accel in radians per sec squared
--     rate       : angular velocity of back tire, can be used to judge speed
--     on_ground  : true if in contact with ground or obstacle
--     on_rail    : true if in contact with rails
--     state      : the state of the mobile's FSM (see mobile.lua)
--
--  AIs should use the following values to control the mobile:
--  in self.mobile:
--     turn       : turns the mobile, should be -1 to 1
--     throt      : state machine for mobile's throttle
--                  adjust with throt:set_state( new_state ).
--                  See mobile.lua for a list of throttle states
--     targ_head  : Normally 0, this value is the target heading (in radians)
--                  used by mobile.stabilize() which makes a small adjustment
--                  each frame to try to keep the mobile oriented along
--                  this heading.
--
--  Also, AI's can query other mobile's positions by refering to the
--  mob[] table defined in main.lua.
--  "table.getn(mob)" will return number of mobiles
--  "for i, m in ipairs(mob) do" will iterate through each element of mob
--    and assign m to that mobile, and i to the mobile's index.
--
--  mob[1] is the user's mobile.


--need funct to create AI
  -- needs to be called in the main loop after new AI car is created
  -- funct to initalize AI var for car
     --  self.variable=0 //initalize var
     -- curent dec line var
     -- curr way point var



-- NOTE ABOUT CHANGING STATES:
-- To change state, call x:set_state(newstate) in your idle loop
-- If there is something you want to occur when the state changes, put that 
--    in the x:do_change_state() function. 
-- You should never explicitly call x:do_change_state(), it is called automatically
--    when you invoke x:set_state()

-- to change throttle, call self.mobile.throt:set_state(STATE_THROT_HIGH)
-- to change ai state, call self:set_state(STATE_AI_FOLLOWWP)

-- NOTE ABOUT THE BIKE WIGGING OUT:
--   Try ramming the bike, You may find that it flips out.  Im not sure what causes
-- this, Im considering adding something that says, if your lateral velocity is too 
-- high, then just dont try to move.

function ai:switchAggressive(behavior)

	if (behavior == "AGGRESSIVE") then
		
		if( not(self.mobile.throt.state == STATE_THROT_BOOST) ) then
			self.mobile.throt:set_state(STATE_THROT_HIGH)
			self.state = STATE_AI_AGGRESSIVE
		end
	else
		if( not(self.mobile.throt.state == STATE_THROT_BOOST) ) then
			self.mobile.throt:set_state(STATE_THROT_LOW)
		end
		self.state = STATE_AI_FOLLOWWP
	end
	

end

-- check if ai should be aggressive based on proximity to the player
function ai:checkPersonality()
	-- this funct must be changed to checkPersonality()
	-- SHY - will always avoid the player, never  attacks
	-- MAD - will always chase the player, always attacks
	-- AGGRESSIVE - will attack the player 70% of the time and even try
	--            - to cut him off when in front of him, not let him pass
	-- FOCUSED - will slowly follow the wps and attack 30% of time
	local distAItoPlayer = pos_distance( self.mobile.px, self.mobile.py,
	                       self.mobile.pz, mob[1].px, mob[1].py, mob[1].pz)
       
    local rand = math.random(1, 100)
    
	if(self.pers == "ANGRY") then

		if( rand <= 70 and (distAItoPlayer < 10 and distAItoPlayer > 4 and
		    math.abs(self.mobile.px - mob[1].px) < 12) and self.mobile.pz < -15)
			then
			
			self:switchAggressive("AGGRESSIVE")
		else
   			self:switchAggressive("PASSIVE")
		end

	elseif(self.pers == "SHY") then

		if(not(self.mobile.throt.state == STATE_THROT_BOOST)) then
		    self.mobile.throt:set_state(STATE_THROT_HIGH)
		end

	elseif(self.pers == "MAD") then

		if( rand <= 95 and (distAItoPlayer < 15 and distAItoPlayer > 4 and
		    math.abs(self.mobile.px - mob[1].px) < 17) and self.mobile.pz < -15)
			then
			
        	self:switchAggressive("AGGRESSIVE")
		else
   			self:switchAggressive("PASSIVE")
		end
	
	elseif(self.pers == "FOCUSED") then

    	if( rand <= 30 and not(self.mobile.throt.state == STATE_THROT_BOOST)) then
		    self.mobile.throt:set_state(STATE_THROT_HIGH)
		end

		if( rand <= 40 and (distAItoPlayer < 8 and distAItoPlayer > 4 and
		    math.abs(self.mobile.px - mob[1].px) < 17) and self.mobile.pz < -15)
			then
			
       		self:switchAggressive("AGGRESSIVE")
		else
   			self:switchAggressive("PASSIVE")
		end
		
	end
end

-- get ai's behavior to either follow WPs or move towards player
function ai:get_coord_behavior(x, y, z)

	if( self.state == STATE_AI_AGGRESSIVE) then


  -- chase the player
		return mob[1].px, 0, mob[1].pz-5
	else -- go for the wp
		return x, y, z
	end

end

--[[

function ai:get_coord_behavior(x, y, z)
 --local rand = math.random(1, 100)

	if( self.state == STATE_AI_AGGRESSIVE ) then

    	if(self.mobile.pz < mob[1].pz) then
  			return mob[1].px, 0, mob[1].pz-5

			-- chase the player
		--	return mob[1].px, 0, mob[1].pz-5
		end

	else -- go for the wp
		return x, y, z
	end

end
--]]


function ai:catchupToPlayer()
    local distAItoPlayer = self.mobile.pz - mob[1].pz
	if( distAItoPlayer > 60 and self.mobile.pz > -2800 and not(self.state == STATE_MOBILE_OOC) ) then
	    self.mobile.throt:set_state(STATE_THROT_BOOST)
	else
		self.mobile.throt:set_state(STATE_THROT_LOW)
	end
end


function ai:do_idle( dt )

    if not (self.mobile.state == STATE_MOBILE_RACING or
	    self.mobile.state == STATE_MOBILE_RESPAWN) then
		return
	end

	if self.state == STATE_AI_FOLLOWWP or self.state == STATE_AI_AGGRESSIVE then

		local wx, wy, wz = self:get_next_wp(self.mobile.id)
        
		local dz  = wz  - self.mobile.pz   -- delta z
		local dx  = wx  - self.mobile.px   -- dalta x
		local ang = math.atan(dx/dz)       -- angle to waypoint
		local da  = ang - self.mobile.ry   -- delta angle (mob heading to ang)
		local fv  = math.abs(self.mobile.vz / self.mobile.max_vel) -- frac for vel
		local lv  = math.abs(self.mobile.vx) -- lateral vel

		--E.print_console(string.format("lv: %7.3f\n", lv))

		self.mobile.targ_head = ang  -- sets target for mobile.stabilize()

		local turn = 0
		if lv < 32 then
		    -- at max speed (fv = 1) if an object is 45deg left or right, use 
		    --   max turn (math.deg(da) * fv / 45 = 45 * 1 / 45 = 1)
		    turn = math.deg(da) * fv / 45 
		    
		    -- bound mobile's turn value (-1 to 1)
		    if turn > 1  then turn = 1  end
		    if turn < -1 then turn = -1 end
		end
		
		-- smooth out turns
		self.mobile.turn = ((self.mobile.turn * (self.smooth - 1)) + turn)
		self.mobile.turn = self.mobile.turn / self.smooth

		-- debug 
		--[[
		local dstr = "%d: da %6.3f, fv %6.3f, lv %6.3f, turn %6.3f\n"
		dstr = string.format(dstr, self.mobile.id, math.deg(da), 
				     fv, lv, self.mobile.turn)
		E.print_console(dstr)
		--]]
		
		-- set throttle, slow down when approaching waypoint
		if ( dz < 50 and not(self.pers == "SHY") ) then
		    self.mobile.throt:set_state(STATE_THROT_LOW)
		else
			self.mobile.throt:set_state(STATE_THROT_HIGH)
		end

		self:checkPersonality() -- decide to chase player or follow wps

		self:catchupToPlayer() -- change throt to high if ai gets too far behind

    end
end



-- based on mobile's position get the next waypoint to go to
function ai:get_next_wp(aiID)
	local x, y, z = 0, 0, -10000000  -- default wp, infinity down track

	local WPs= {}
    
    if(aiID == 2) then
    	WPs = track.waypoints1
	elseif (aiID == 3) then
		WPs = track.waypoints2
    elseif (aiID == 4) then
		WPs = track.waypoints3
	 -- you can add other waypoint "tracks" for AIs here--
	end	

	-- iterate through all waypoints on the track
    for i, line in ipairs(WPs) do

		--self:checkAggressive() -- decide if to go into aggressive mode

		-- go through each wp in the randomly chosen group
		for j, waypoint in ipairs( line.offsets ) do
			 -- break down waypoint position
			local wx, wy, wz = E.get_entity_position(waypoint)
			-- if waypoint has not been passed yet
			if( wz <= self.mobile.pz ) then

				-- if not too close then set as next waypoint
			    local dist_to_wp = self.mobile.pz - wz
				if dist_to_wp > 5 then
					x, y, z = wx, wy, wz
					return self:get_coord_behavior(x, y, z)
				end
			end

		end -- end inner for-loop

	end -- end outer for-loop
	return self:get_coord_behavior(x, y, z)
	
	
end

--[[
function ai:do_change_state(prev_state, new_state)
	if(prev_state == STATE_THROT_HIGH or prev_state == STATE_THROT_LOW)
	then
		self.mobile.throt:set_state(new_state)
	elseif(prev_state == STATE_AI_FOLLOWWP or prev_state == STATE_AI_AGGRESSIVE)
	then
        self.state = new_state
	else
	    E.print_console("Error: " ..prev_state.. "is invalid" .. "\n")
	end

end
--]]