-- semi dependencies
if not FSM_LUA     then dofile("fsm.lua") end
if not SCREEN_LUA  then dofile("screen.lua") end
if not TRACK_LUA   then dofile("track.lua") end

GAMEFSM_LUA = true

STATE_GAME_LOAD     = "LOADING"
STATE_GAME_MENU     = "MENU"
STATE_GAME_INIT     = "INIT"
STATE_GAME_READY    = "READY"
STATE_GAME_SET      = "SET"
STATE_GAME_RACING   = "RACING"
STATE_GAME_FINISH   = "FINISH"
STATE_GAME_ADDINIT  = "ADDI"

gamefsm = FSM:instantiate{state = STATE_NONE, tostr = "GAME_FSM"}

gamefsm.rsg_time = 1.4
--gamefsm.loadtime = 8
gamefsm.loadtime = 20
--gamefsm.rsg_time = .

function gamefsm:flash( page, time, nosound )
    if not nosound then E.play_sound(sounds[page]) end
    self.page_life = self.state_time + time
    screen:turn_page(screen.pages[page], 2)
end

function gamefsm:advance_init()

    E.set_entity_scale(screen.newinits[self.current_init],
		       0.125, 0.25, 1)

    self.current_init = self.current_init + 1

    E.play_sound(sounds.menu_select)

    if self.current_init > 3 then
	scores:add_score(screen.newinits.str, "default", screen.highscore.time)
	screen:reload_scores()

	set_init_sprite(screen.newinits, "_", 1)
	set_init_sprite(screen.newinits, "_", 2)
	set_init_sprite(screen.newinits, "_", 3)

	do_reset_world()
	self:set_state(STATE_GAME_MENU)
	screen:show_menu("scores", true, 5)
	return
    end

    self.current_char = "A"
    self.choice_time = self.state_time
    set_init_sprite(screen.newinits, "A", self.current_init)

end

function gamefsm:do_idle ( dt )
    self.state_time = self.state_time + dt
    
    if self.state == STATE_GAME_LOAD then
    elseif self.state == STATE_GAME_INIT then
	if self.state_time > self.rsg_time then
	    self:set_state(STATE_GAME_READY)
	end
    elseif self.state == STATE_GAME_READY then
	if self.state_time > self.rsg_time then
	    self:set_state(STATE_GAME_SET)
	end
    elseif self.state == STATE_GAME_SET then
	if self.state_time > self.rsg_time then
	    self:set_state(STATE_GAME_RACING)
	end
    elseif (self.state == STATE_GAME_RACING) then

	if self.state_time > self.rsg_time and self.gopage then
	    screen:turn_page()
	    self.gopage = nil
	end

	if self.page_life and self.state_time > self.page_life then
	    screen:turn_page()
	    self.page_life = nil
	end

	--screen:set_string ( "time", format_time( self.state_time ) )
	screen:update_timer( self.state_time )

    elseif self.state == STATE_GAME_MENU
        or self.state == STATE_GAME_FINISH 
	or self.state == STATE_GAME_ADDINIT then

	local jx, jy = E.get_joystick(0)

	if jx > -0.5 and jx < 0.5 then
	    self.joy_neutral = true
	else
	    if self.joy_neutral then

		local c_opt    = screen.cur_option
		local c_opt_on = screen.cur_menu[c_opt].on
		E.set_entity_scale(c_opt_on, 1, 1, 1)
		self.choice_time  = self.state_time

		if jx < -0.5 then
		    if self.state == STATE_GAME_MENU 
		    or self.state == STATE_GAME_FINISH then
			-- choose last one
			local nextoption = screen.cur_option - 1
			if nextoption < 1 then
			    nextoption = screen.cur_menu.num_options
			end
			screen:set_menu_option(nextoption)
		    else
			-- scroll back one char
			self.current_char = prev_letter(self.current_char)
			set_init_sprite(screen.newinits, 
					self.current_char, 
					self.current_init)
			E.play_sound(sounds.menu_click)
		    end
		elseif jx > 0.5 then
		    if self.state == STATE_GAME_MENU 
		    or self.state == STATE_GAME_FINISH then
			-- choose next one
			local nextoption = screen.cur_option + 1
			if nextoption > screen.cur_menu.num_options then
			    nextoption = 1
			end
			screen:set_menu_option(nextoption)
		    else
			-- scroll forward one char
			self.current_char = next_letter(self.current_char)
			set_init_sprite(screen.newinits, 
					self.current_char, 
					self.current_init)
			E.play_sound(sounds.menu_click)
		    end
		end
	    end
	    self.joy_neutral = false
	end

	-- make current selection pulse
	local t = self.state_time - self.choice_time
	local wave = math.sin(t * math.pi)
	local env  = 0
	if t < 1 then env = 1 / (t*4 + 1) end
	local scale = (1 + wave * env * 0.5)

	if self.state == STATE_GAME_ADDINIT then
	    E.set_entity_scale(screen.newinits[self.current_init],
			       scale*0.125, scale*0.25, 1)
	else
	    E.set_entity_scale(screen.cur_menu[screen.cur_option].on,
			       scale, scale, 1)
	end
    end
end

function gamefsm:do_change_state ( prev_state, new_state )

    if prev_state == STATE_GAME_MENU then
	E.stop_sound(sounds.menu_music)
    end

    if new_state == STATE_GAME_READY  then
	screen:turn_page(screen.pages["ready"], 2)
	E.play_sound(sounds.rdyset)
	track:enable_hazards(true)
    elseif new_state == STATE_GAME_SET then
	screen:turn_page(screen.pages["set"], 2)
	E.play_sound(sounds.rdyset)
    elseif new_state == STATE_GAME_RACING then
	screen:turn_page(screen.pages["go"], 2)
	self.gopage = true
	E.play_sound(sounds.go)
	E.loop_sound(sounds.race_music)
	self.race_music = true
    elseif new_state == STATE_GAME_FINISH then
	self.joy_neutral = true
	self.choice_time = 0
    elseif new_state == STATE_GAME_MENU then
	self.joy_neutral = true
	self.choice_time = 0
	if self.race_music then 
	    E.stop_sound(sounds.race_music)
	end
	E.loop_sound(sounds.menu_music)
    elseif new_state == STATE_GAME_ADDINIT then
	self.joy_neutral = true
	screen:turn_page(screen.pages["inits"], 2)
	self.current_init = 1
	self.current_char = "A"
	self.choice_time = 0
	set_init_sprite(screen.newinits, "A", 1)
    end
    
end