from bge import logic, events
from threading import Thread
import socket
import pickle
import time
import clientLobby

def connect( ):
	scene = logic.getCurrentScene()

	sensor = scene.objects["StartSensor"]
	if sensor["active"] == False:
		return
	updateGUI( scene )

	clientSocket = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
	clientSocket.setblocking( False )

	ipT = scene.objects["TextIp"]["Text"]
	portT = scene.objects["TextPort"]["Text"]
	nameT = scene.objects["TextName"]["Text"]

	try:
		port = int( portT )
	except:
		restoreGUI( scene )
		showErrorMsg( scene, "PortError" )
		return

	server_address = ( ipT, port )

	if send( clientSocket, server_address, nameT ):
		Thread( target=receive, args=[ clientSocket, scene ] ).start()
	else:
		restoreGUI( scene )
		showErrorMsg( scene, "AddressError" )

def send( clientSocket, address, name ):
	join_data = {"JOIN":name}
	pickled_data = pickle.dumps( join_data, 2 )
	try:
		clientSocket.sendto( pickled_data, address )
	except:
		return False
	return True

def receive( clientSocket, scene ):
	connected = False
	timeout = time.clock()

	while not connected and time.clock() - timeout < 10:
		try:
			data, address = clientSocket.recvfrom( 2048 )

			unpickled_data = pickle.loads( data )

			if "CONNECTED" in unpickled_data:
				connected = True
				Thread( target=clientLobby.initLobby, args=[ clientSocket, address, unpickled_data ] ).start()

			elif "REJECTED" in unpickled_data:
				reason = unpickled_data["REJECTED"]
				if reason == "SERVER_FULL":
					restoreGUI( scene )
					showErrorMsg( scene, "ServerFull" )
					return

				elif reason == "NAME_TAKEN":
					restoreGUI( scene )
					showErrorMsg( scene, "NameTaken" )
					return

		except socket.error:
			pass

	if not connected:
		restoreGUI( scene )
		showErrorMsg( scene, "ConnectError" )

def updateGUI( scene ):
	connectSensor = scene.objects["StartSensor"]
	connectSensor["active"] = False

	scene.objects["Connect"].setVisible( False, False )
	scene.objects["Connecting"].setVisible( True, False )

	backSensor = scene.objects["BackSensor"]
	backSensor["active"] = False
	scene.objects["Back"].setVisible( False, False )

def restoreGUI( scene ):
	connectSensor = scene.objects["StartSensor"]
	connectSensor["active"] = True

	scene.objects["Connect"].setVisible( True, False )
	scene.objects["Connecting"].setVisible( False, False )

	backSensor = scene.objects["BackSensor"]
	backSensor["active"] = True
	scene.objects["Back"].setVisible( True, False )

def showErrorMsg( scene, msg ):
	spawner = scene.objects["ErrorMsgSpawner"]
	other_player = scene.addObject( msg, spawner, 180 )