-------------------------------------------------------------------------------
--  Finite State Machine 
-------------------------------------------------------------------------------
function FSM( t )
  t.sendEvent = function( self, eventName, eventItem )
    local event = { name = eventName, item = eventItem }
    self.tEventQueue[#(self.tEventQueue) + 1] = event
    --log( "Sent Event: " .. event.name )
  end
  
  t.tEventQueue = {}
  
  t.setState = function( self, state )
    if self.curState ~= nil then
        self.prevState = self.curState.sName
    end
    self.curState = self[state]
    if self.curState ~= nil then
        self.curState.sName = state
        local activity = self.curState.activity
        if activity ~= nil then 
            activity() 
        end
    end
  end
  
  t.stop = function( self )
    self.curState = nil
  end

  t.run = function( self, state )
    local fDeltaTime = 0.02
    self:setState( state )    
    local bRunning = (self.curState ~= nil)
    while bRunning do
        -- take next event from the queue
        local event = self.tEventQueue[1]
        for i, f in ipairs( self.curState ) do
            local item   = nil
            local bGuard = false
            local bEvent = false
     
            if event ~= nil then
                item = event.item 
                bEvent = (f.event ~= nil and f.event == event.name)
                if bEvent then
                    bGuard = (f.guard == nil or (f.guard ~= nil and f.guard( item ) == true))
                end
            elseif f.event == nil then
                bGuard = (f.guard ~= nil and f.guard() == true)
                bEvent = bGuard
            end
            
            if bGuard and bEvent then
                if self.curState ~= nil and self.curState.exitaction ~= nil then
                    self.curState.exitaction()
                end
                --  do action
                if f.action ~= nil then 
                    f.action( item ) 
                end
                -- switch state
                if f.state ~= nil then
                    self:setState( f.state )
                    --log( "Switched to State: " .. f.state )
                end
                do break end
            end
        end
        -- queue shift         
        if event ~= nil then
            --log( "Removing Event: " .. event.name )
            for i, f in ipairs( self.tEventQueue ) do
                self.tEventQueue[i] = self.tEventQueue[i + 1]
            end
        end
        
        if self.curState == nil then 
            --log( "Switched to nil state!" )
            bRunning = false 
        end
        wait( fDeltaTime )
    end
      
  end

  return t
end
