#! /usr/bin/env python
'''
Example server
'''

from twisted.spread import pb

def Debug( msg ):
        return
        #print msg

DIRECTION_UP = 0
DIRECTION_RIGHT = 1
DIRECTION_LEFT = 2
DIRECTION_DOWN = 3

class Event:
        """this is a superclass for any events that might be generated by an
        object and sent to the EventManager"""
        def __init__(self):
                self.name = "Generic Event"

class TickEvent(Event):
        def __init__(self):
                self.name = "CPU Tick Event"

class QuitEvent(Event):
        def __init__(self):
                self.name = "Program Quit Event"

class MapBuiltEvent(Event):
        def __init__(self, gameMap):
                self.name = "Map Finished Building Event"
                self.map = gameMap

class GameStartRequest(Event):
        def __init__(self):
                self.name = "Game Start Request"

class GameStartedEvent(Event):
        def __init__(self, game):
                self.name = "Game Started Event"
                self.game = game

class CharactorMoveRequest(Event):
        def __init__(self, direction):
                self.name = "Charactor Move Request"
                self.direction = direction

class CharactorPlaceEvent(Event):
        """this event occurs when a Charactor is *placed* in a sector,
        ie it doesn't move there from an adjacent sector."""
        def __init__(self, charactor):
                self.name = "Charactor Placement Event"
                self.charactor = charactor

class CharactorMoveEvent(Event):
        def __init__(self, charactor):
                self.name = "Charactor Move Event"
                self.charactor = charactor

#------------------------------------------------------------------------------
class EventManager:
        """this object is responsible for coordinating most communication
        between the Model, View, and Controller."""
        def __init__(self ):
                from weakref import WeakKeyDictionary
                self.listeners = WeakKeyDictionary()
                self.eventQueue= []

        #----------------------------------------------------------------------
        def RegisterListener( self, listener ):
                self.listeners[ listener ] = 1

        #----------------------------------------------------------------------
        def UnregisterListener( self, listener ):
                if listener in self.listeners:
                        del self.listeners[ listener ]
                
        #----------------------------------------------------------------------
        def Notify( self, event ):
                if not isinstance(event, TickEvent):
                        Debug( "     Message: " + event.name )
                for listener in self.listeners:
                        #NOTE: If the weakref has died, it will be
                        #automatically removed, so we don't have
                        #to worry about it.
                        listener.Notify( event )


#------------------------------------------------------------------------------
class NetworkClientController(pb.Root):
        """..."""
        def __init__(self, evManager):
                self.evManager = evManager
                self.evManager.RegisterListener( self )

        #----------------------------------------------------------------------
        def remote_GameStartRequest(self):
                ev = GameStartRequest( )
                self.evManager.Notify( ev )
                return 1

        #----------------------------------------------------------------------
        def remote_CharactorMoveRequest(self, direction):
                ev = CharactorMoveRequest( direction )
                self.evManager.Notify( ev )
                return 1

        #----------------------------------------------------------------------
        def Notify(self, event):
                pass


#------------------------------------------------------------------------------
class TextLogView:
        """..."""
        def __init__(self, evManager):
                self.evManager = evManager
                self.evManager.RegisterListener( self )


        #----------------------------------------------------------------------
        def Notify(self, event):

                if isinstance( event, CharactorPlaceEvent ):
                        print event.name, " at ", event.charactor.sector

                elif isinstance( event, CharactorMoveEvent ):
                        print event.name, " to ", event.charactor.sector

                elif not isinstance( event, TickEvent ):
                        print event.name

#------------------------------------------------------------------------------
class Game:
        """..."""

        STATE_PREPARING = 0
        STATE_RUNNING = 1
        STATE_PAUSED = 2

        #----------------------------------------------------------------------
        def __init__(self, evManager):
                self.evManager = evManager
                self.evManager.RegisterListener( self )

                self.state = Game.STATE_PREPARING
                
                self.players = [ Player(evManager) ]
                self.map = Map( evManager )

        #----------------------------------------------------------------------
        def Start(self):
                self.map.Build()
                self.state = Game.STATE_RUNNING
                ev = GameStartedEvent( self )
                self.evManager.Notify( ev )

        #----------------------------------------------------------------------
        def Notify(self, event):
                if isinstance( event, GameStartRequest ):
                        if self.state == Game.STATE_PREPARING:
                                self.Start()

#------------------------------------------------------------------------------
class Player:
        """..."""
        def __init__(self, evManager):
                self.evManager = evManager
                #self.evManager.RegisterListener( self )

                self.charactors = [ Charactor(evManager) ]

#------------------------------------------------------------------------------
class Charactor:
        """..."""

        STATE_INACTIVE = 0
        STATE_ACTIVE = 1

        def __init__(self, evManager):
                self.evManager = evManager
                self.evManager.RegisterListener( self )
                self.sector = None
                self.state = Charactor.STATE_INACTIVE

        #----------------------------------------------------------------------
        def Move(self, direction):
                if self.state == Charactor.STATE_INACTIVE:
                        return

                if self.sector.MovePossible( direction ):
                        newSector = self.sector.neighbors[direction]
                        self.sector = newSector
                        ev = CharactorMoveEvent( self )
                        self.evManager.Notify( ev )

        #----------------------------------------------------------------------
        def Place(self, sector):
                self.sector = sector
                ev = CharactorPlaceEvent( self )
                self.evManager.Notify( ev )

        #----------------------------------------------------------------------
        def Notify(self, event):
                if isinstance( event, GameStartedEvent ):
                        gameMap = event.game.map
                        self.Place( gameMap.sectors[gameMap.startSectorIndex] )
                        self.state = Charactor.STATE_ACTIVE

                elif isinstance( event, CharactorMoveRequest ):
                        self.Move( event.direction )

#------------------------------------------------------------------------------
class Map:
        """..."""
        def __init__(self, evManager):
                self.evManager = evManager
                #self.evManager.RegisterListener( self )

                self.sectors = range(9)
                self.startSectorIndex = 0

        #----------------------------------------------------------------------
        def Build(self):
                for i in range(9):
                        self.sectors[i] = Sector( self.evManager )

                self.sectors[3].neighbors[DIRECTION_UP] = self.sectors[0]
                self.sectors[4].neighbors[DIRECTION_UP] = self.sectors[1]
                self.sectors[5].neighbors[DIRECTION_UP] = self.sectors[2]
                self.sectors[6].neighbors[DIRECTION_UP] = self.sectors[3]
                self.sectors[7].neighbors[DIRECTION_UP] = self.sectors[4]
                self.sectors[8].neighbors[DIRECTION_UP] = self.sectors[5]

                self.sectors[0].neighbors[DIRECTION_RIGHT] = self.sectors[1]
                self.sectors[1].neighbors[DIRECTION_RIGHT] = self.sectors[2]
                self.sectors[3].neighbors[DIRECTION_RIGHT] = self.sectors[4]
                self.sectors[4].neighbors[DIRECTION_RIGHT] = self.sectors[5]
                self.sectors[6].neighbors[DIRECTION_RIGHT] = self.sectors[7]
                self.sectors[7].neighbors[DIRECTION_RIGHT] = self.sectors[8]

                self.sectors[0].neighbors[DIRECTION_DOWN] = self.sectors[3]
                self.sectors[1].neighbors[DIRECTION_DOWN] = self.sectors[4]
                self.sectors[2].neighbors[DIRECTION_DOWN] = self.sectors[5]
                self.sectors[3].neighbors[DIRECTION_DOWN] = self.sectors[6]
                self.sectors[4].neighbors[DIRECTION_DOWN] = self.sectors[7]
                self.sectors[5].neighbors[DIRECTION_DOWN] = self.sectors[8]

                self.sectors[1].neighbors[DIRECTION_LEFT] = self.sectors[0]
                self.sectors[2].neighbors[DIRECTION_LEFT] = self.sectors[1]
                self.sectors[4].neighbors[DIRECTION_LEFT] = self.sectors[3]
                self.sectors[5].neighbors[DIRECTION_LEFT] = self.sectors[4]
                self.sectors[7].neighbors[DIRECTION_LEFT] = self.sectors[6]
                self.sectors[8].neighbors[DIRECTION_LEFT] = self.sectors[7]

                ev = MapBuiltEvent( self )
                self.evManager.Notify( ev )

#------------------------------------------------------------------------------
class Sector:
        """..."""
        def __init__(self, evManager):
                self.evManager = evManager
                #self.evManager.RegisterListener( self )

                self.neighbors = range(4)

                self.neighbors[DIRECTION_UP] = None
                self.neighbors[DIRECTION_RIGHT] = None
                self.neighbors[DIRECTION_DOWN] = None
                self.neighbors[DIRECTION_LEFT] = None

        #----------------------------------------------------------------------
        def MovePossible(self, direction):
                if self.neighbors[direction]:
                        return 1


#------------------------------------------------------------------------------
def main():
        """..."""
        evManager = EventManager()

        log = TextLogView( evManager )
        clientController = NetworkClientController( evManager )
        game = Game( evManager )
        
        from twisted.internet import reactor

        reactor.listenTCP( 8000, pb.PBServerFactory(clientController) )

        reactor.run()

if __name__ == "__main__":
        main()