from Queue import Queue

class Sprite(object):
    """ base class for sprites (in-game objects) """
    group = ''
    def __init__(self, id, game):
        self.id = id
        self.game = game
        
    def calculate_state(self, framestates, time_spent):
        """ calculate the sprite's current position and state

            this is called first thing on every frame
        """
        self.commands = Queue()

    def handle_changes(self, framestates, time_spent):
        """ handle any changes in the game state

            here things like collision detection, score adjustments and
            level changes and such are dealt with

            this is called after calculate_position
        """
        # make sure you don't emit unnecessary info!

    def get_create_commands(self):
        """ return a list of commands causing our addition
        """
        return []

    def get_frame_commands(self):
        """ return a list of all change commands for the current frame

            this.is called last thing for each frame (after calculate_position
            and handle_changes)

            the return values should be tuples (id, command), where id is
            the id of the client to send it to, and command the serialized
            command - use -1 as id to send a command to all clients, use
            -2 to send to all clients except a newly created one (this is
            used to avoid creating user sprites twice)
        """
        while not self.commands.empty():
            yield self.commands.get()

    def get_del_commands(self):
        """ return a list of commands causing our removal
        """
        return []

class Game(object):
    """ base class for game (world) objects """

    def __init__(self):
        self.sprites = {}
        self.commands = Queue()

    def initialize(self, engine):
        self.engine = engine

    def add_user(self, id):
        pass

    def del_user(self, id):
        pass

    def add_sprite(self, sprite):
        self.sprites[sprite.id] = sprite
        commands = sprite.get_create_commands()
        for command in commands:
            self.commands.put((-2, command))

    def del_sprite(self, id):
        sprite = self.sprites.pop(id)
        commands = sprite.get_del_commands()
        for command in commands:
            self.commands.put((-1, command))

    def get_sprite(self, id):
        return self.sprites[id]

    def get_sprite_group(self, group):
        return (s for s in self.sprites.values() if s.group == group)

    def calculate_state(self, framestates, timespent):
        for id, sprite in self.sprites.items():
            sprite.calculate_state(framestates, timespent)

    def handle_changes(self, framestates, timespent):
        for id, sprite in self.sprites.items():
            sprite.handle_changes(framestates, timespent)

    def get_create_commands(self):
        for id, sprite in self.sprites.items():
            for command in sprite.get_create_commands():
                yield command

    def get_frame_commands(self):
        while not self.commands.empty():
            yield self.commands.get()
        for id, sprite in self.sprites.items():
            for command in sprite.get_frame_commands():
                yield command


