------------------------------------------------
-- Creates a new automaton used to handle the
-- different states of the game (menus, game...)
------------------------------------------------
function newAutomaton()
   local o = {}
   
   
   -------------------------------
   -- Constructor of the automaton
   -------------------------------
   function o:construct()
      self.states = {}
      self.currentState = 0
      
      return self
   end
   
   
   ------------------------------------
   -- Adds a new state to the automaton
   ------------------------------------
   function o:addState(name, load, update, draw)
      local state =
      {
         name = name,
         load = load,
         update = update,
         draw = draw,
      }
      table.insert(self.states, state)
      
      if (self.currentState == 0) then
         self:setCurrentState(name)
      end
   end
   
   
   ------------------------------------------------
   -- Sets the current state of the automaton.
   -- It will call the "load" callback of the state
   ------------------------------------------------
   function o:setCurrentState(name)
      for k, state in ipairs(self.states) do
         if (state.name == name) then
            self.currentState = k
            if (state.load) then
               state.load()
            end
            return true
         end
      end
      return false
   end
   
   
   ---------------------------------------------
   -- Returns the current state of the automaton
   ---------------------------------------------
   function o:getCurrentState()
      if (self.currentState == 0) then
         return nil
      else
         return self.states[self.currentState].name
      end
   end
   
   
   ----------------------------------------------------
   -- Calls the "update" callback of the current state
   ----------------------------------------------------
   function o:update(dt)
      if (self.currentState ~= 0) then
         local state = self.states[self.currentState]
         if (state.update) then
            local next = state.update(dt)
            if (next) then
               if (self:setCurrentState(next)) then
                  controls.clear()
                  self:update(0)
               end
            end
         end
      end
   end
   
   
   ----------------------------------------------------
   -- Calls the "draw" callback of the current state
   ----------------------------------------------------
   function o:draw()
      if (self.currentState ~= 0) then
         local state = self.states[self.currentState]
         if (state.draw) then
            state.draw()
         end
      end
   end
   
   
   return o:construct()
end
