
import string
from Selecting.SelectManager import ChannelHandler
from socket import socket, AF_INET, SOCK_STREAM
from ClientEvent import Event
from Selecting.TCPServer import ConnectionSocket
import ClientDefaults

class UndefProto (ChannelHandler):
	def __init__(s, evq, selector, sev):
		s.evq = evq
		s.selector = selector
		s.sev = sev
		s.init()
		s.sev.reg_proto(s)

	def init(s):
		s.protocols = {		'0.3'	: Ver03Proto }
		s.cmdhandlers = {	'GSRV'	: s.gsrv }
		s.eventhandlers = {	'connect_to' : s.connect_to }
	
	def start(s):
		pass

	def receive(s, data):
		print "Got:", data
		cmd = string.split(data)
		args = {}
		margs = []
		try:
			for a in cmd[1:]:
				aval = string.split(a, "=")
				try:
					args[string.lower(aval[0])] = aval[1]
				except IndexError:
					margs.append(a)
		except IndexError:
			pass
		try:
			handler = s.cmdhandlers[string.upper(cmd[0])]
		except (KeyError, IndexError):
			s.send("ERRC unknown command %s" % data)
			return
		handler(cmd[0], args, margs)
	
	def cleanup(s):
		pass
	
	def reg_conn(s, conn):
		print "Registering connection %s for %s" % (conn, s)
		s.conn = conn
		conn.reg_handler(s)
		s.start()
	
	def send(s, data):
		print "Sending:", data
		s.conn.write(data)

	def recv_event(s, ev):
		try:
			handler = s.eventhandlers[ev.type]
		except KeyError:
			print "No handler for event type %s in %s" % (ev.type, s)
			return
		handler(ev)
		
	def send_event(s, ev):
		s.evq.recv_event(ev)

	def gsrv(s, cmd, args, margs):
		try:
			proto = s.protocols[margs[0]]
		except KeyError:
			s.send("QUIT")
			return
		newproto = proto(s.evq, s.selector, s.sev)
		newproto.reg_conn(s.conn)
	
	def connect_to(s, ev):
		host = ev.name
		port = ev.quant
		print "connecting to (%s, %s)" % (host, port)
		sock = socket(AF_INET, SOCK_STREAM)
		sock.connect((host, port))
		cs = ConnectionSocket(sock, s)
		s.reg_conn(cs)
		s.selector.add_channel(cs)
		
		
		
class Ver03Proto (UndefProto):
	def init(s):
		s.eventhandlers = {	'JOIN'	: s.join,
							'FILD'	: s.fild,
							'PGAM'	: s.pgam,
							'MESG'	: s.mesg,
							'SUIC'	: s.suic,
							'QUIT'	: s.quit,
							'MOVE'	: s.move,
							'DONE'	: s.done	}

		s.cmdhandlers = {	'CLOK'	: s.clok,
							'BGML'	: s.bgml,
							'GAME'	: s.game,
							'CFLD'	: s.cfld,
							'EGML'	: s.egml,
							'SLCT'	: s.slct,
							'OKAY'	: s.okay,
							'GOWN'	: s.gown,
							'PLYR'	: s.plyr,
							'PLNT'	: s.plnt,
							'TIME'	: s.time,
							'GFLD'	: s.gfld,
							'PIND'	: s.pind,
							'PSHP'	: s.pshp,
							'YEAR'	: s.year,
							'BRND'	: s.brnd,
							'SAID'	: s.said,
							'PKIL'	: s.pkil,
							'KILL'	: s.kill,
							'WINN'	: s.winn,
							'MVOK'	: s.mvok,
							'PDON'	: s.pdon,
							'ERND'	: s.ernd,
							'BATT'	: s.batt,
							'BSHP'	: s.bshp,
							'BWIN'	: s.bwin,
							'FORT'	: s.fort,
							'ERRC'	: s.error,
							'ERRP'	: s.error,
							'ERRS'	: s.error	}
	
	def start(s):
		str = "GCLT 0.3 %s" % ClientDefaults.ClientName
		s.send(str)

	# Client-to-server commands
							
	def join(s, ev):
		str = "JOIN g=%d name=%s %s" % (ev.game, ev.name, ev.extra)
		s.send(str)
	
	def fild(s, ev):
		str = "FILD g=%d x=%d y=%d pl=%d" % (ev.game, ev.x, ev.y, ev.quant)
		s.send(str)
	
	def pgam(s, ev):
		str = "PGAM g=%d type=%s" % (ev.game, ev.cmd)
		s.send(str)
	
	def mesg(s, ev):
		str = "MESG %s" % ev.extra
		s.send(str)
	
	def suic(s, ev):
		str = "SUIC %s" % ev.extra
		s.send(str)
	
	def quit(s, ev):
		str = "QUIT"
		s.send(str)
	
	def move(s, ev):
		str = "MOVE from=%d to=%d s=%s" % (ev.scr, ev.dst, ev.quant)
		s.send(str)
	
	def done(s, ev):
		str = "DONE"
		s.send(str)
	
	# Server-to-client commands
	
	def mksimple(s, cmd):
		s.send_event(Event(cmd))

	def clok(s, cmd, args, margs):
		s.mksimple(cmd)
	
	def bgml(s, cmd, args, margs):
		s.mksimple(cmd)
	
	def game(s, cmd, args, margs):
		s.send_event(Event(	cmd,
							game=args['g'], 
							player=args['owner'],
							name=args['name'],
							extra=margs))
	def cfld(s, cmd, args, margs):
		s.send_event(Event(	cmd,
							game=args['g'],
							x=args['x'],
							y=args['y'],
							name=args['name'],
							quant=args['pl']))
	
	def egml(s, cmd, args, margs):
		s.mksimple(cmd)
	
	def slct(s, cmd, args, margs):
		s.mksimple(cmd)
	
	def okay(s, cmd, args, margs):
		s.send_event(Event(	cmd,
							cmd=args['cmd']))
	
	def gown(s, cmd, args, margs):
		s.send_event(Event( cmd,
							game=args['g'],
							player=args['p']))
	
	def plyr(s, cmd, args, margs):
		s.send_event(Event( cmd,
							player=args['p'],
							name=args['name'],
							extra=margs))
		
	def plnt(s, cmd, args, margs):
		s.send_event(Event( cmd,
							planet=args['i'],
							player=args['owner'],
							x=args['x'],
							y=args['y']))
	
	def time(s, cmd, args, margs):
		s.send_event(Event( cmd,
							year=args['y']))
	
	def gfld(s, cmd, args, margs):
		s.send_event(Event( cmd,
							game=args['g'],
							x=args['x'],
							y=args['y'],
							name=args['name'],
							quant=args['pl']))
	
	def pind(s, cmd, args, margs):
		s.send_event(Event( cmd,
							planet=args['i'],
							quant=args['indust']))
	
	def pshp(s, cmd, args, margs):
		planet = args['i']
		del args['i']
		s.send_event(Event(	cmd,
							planet=planet,
							ships=args))
	
	def year(s, cmd, args, margs):
		s.send_event(Event(	cmd,
							year=args['y']))
	
	def brnd(s, cmd, args, margs):
		s.mksimple(cmd)
	
	def said(s, cmd, args, margs):
		s.send_event(Event( cmd,
							player=args['sayer'],
							extra=margs))
	
	def pkil(s, cmd, args, margs):
		s.send_event(Event( cmd,
							player=args['p'],
							extra=margs))
	
	def kill(s, cmd, args, margs):
		s.send_event(Event( cmd,
							player=args['p']))
	
	def winn(s, cmd, args, margs):
		s.send_event(Event( cmd,
							player=args['p']))
	
	def mvok(s, cmd, args, margs):
		s.send_event(Event( cmd,
							quant=args['remain'],
							year=args['eta']))
	
	def pdon(s, cmd, args, margs):
		s.send_event(Event( cmd,
							player=args['p']))
	
	def ernd(s, cmd, args, margs):
		s.mksimple(cmd)
	
	def batt(s, cmd, args, margs):
		s.send_event(Event( cmd,
							planet=args['i'],
							src=args['att'],
							dst=args['def'],
							flag=args['surprise']))
	
	def bshp(s, cmd, args, margs):
		planet = args['i']
		del args['i']
		s.send_event(Event( cmd,
							planet=planet,
							ships=args))
	def bwin(s, cmd, args, margs):
		s.send_event(Event( cmd,
							planet=args['i'],
							player=args['winner']))
	
	def fort(s, cmd, args, margs):
		planet = args['i']
		quant = args['new']
		del args['i']
		del args['new']

		s.send_event(Event( cmd,
							planet=planet,
							quant=quant,
							ships=args))
	
	def error(s, cmd, args, margs):
		s.send_event(Event( cmd,
#	not in server			cmd=args['cmd'],
							extra=margs))
