'''
Created on 19 maj 2014

@author: Reii
'''

import socket
import pickle
import server
import constants

class ServerLobby: 

    def __init__( self, server ):
        self.server = server
        self.users = server.address_to_user
        self.colors = server.availableColors
        self.socket = server.socket
        self.gameStarted = False

    def run( self ):

        while self.server.running and not self.gameStarted:
            self.receive()


    def receive( self ):
        try: 
            data, address = self.socket.recvfrom( 1024 )

            unpickled_data = pickle.loads( data )

            if constants.MSG_JOIN in unpickled_data:
                self.playerJoined( unpickled_data, address )

            elif constants.MSG_LEAVE in unpickled_data:
                self.playerLeft( address )

            elif constants.MSG_READY in unpickled_data:
                self.playerReady( address )

            elif constants.MSG_NOT_READY in unpickled_data:
                self.playerNotReady( address )

        except socket.error:
            return


    def playerJoined( self, data, address ):
        name = data[ constants.MSG_JOIN ]
        
        if self.serverFull( ):
            data = { constants.MSG_REJECTED:constants.MSG_REASON_FULL }
            self.server.sendTo( data, address )
            return
        
        if self.nameTaken( name ):
            data = { constants.MSG_REJECTED:constants.MSG_REASON_NAME }
            self.server.sendTo( data, address )
            return
                    
        colorKey = self.colors.keys()[0]
        color = self.colors.pop( colorKey, None )
        self.users[ address ] = server.Player( name, ( colorKey, color ) )
        
        broadcastMsg = { constants.MSG_JOIN:{ constants.MSG_PROP_COLOR:colorKey, constants.MSG_PROP_NAME:name } }
        self.server.sendExclude( broadcastMsg, address )
        
        connectMsg = self.resolveConnectMsg( colorKey )
        self.server.sendTo( connectMsg, address )
        
    def resolveConnectMsg( self, playerColorKey ):
        players = {}
        for address in self.users:
            user = self.users[ address ]
            color = user.color[0]
            readyStatus = user.ready
            players[ user.name ] = { constants.MSG_PROP_COLOR:color, constants.MSG_PROP_READY:readyStatus }
        
        return { constants.MSG_CONNECTED:{ constants.MSG_PLAYERS:players, constants.MSG_GAMETIME:self.server.gameTime, constants.MSG_CLIENT_COLOR:playerColorKey } }
    
    def serverFull( self ):
        if len( self.users ) == self.server.maxPlayers:
            return True
        return False
    
    def nameTaken( self, name ):
        for address in self.users:
            user = self.users[ address ]
            if user.name == name:
                return True
        return False
    
    def playerLeft( self, address ):
        player = self.users.pop( address, None )
        colorKey, color = player.color
        self.colors.update( {colorKey:color} )
        
        msg = { constants.MSG_LEAVE:player.colorKey }
        self.server.send( msg )
        
        self.tryStartGame( )

    def playerReady( self, address ):
        player = self.users[ address ]
        player.ready = True
        
        msg = { constants.MSG_READY:player.color[0] }
        self.server.send( msg )
        
        self.tryStartGame( )

    def playerNotReady( self, address ):
        player = self.users[ address ]
        player.ready = False
        
        msg = { constants.MSG_NOT_READY:player.color[0] }
        self.server.send( msg )

    def tryStartGame( self ):
        for user in self.users:
            player = self.users[user]
            if not player.ready:
                return 
        self.startGame()

    def startGame( self ):
        self.server.openGame( )
        self.gameStarted = True
    