
from Tkinter import *
from ClientEvent import Event, InterfaceElement, SimpleInterfaceElement
from ClientDialog import GameSelectDialog, ConnectDialog
import ClientDefaults
import string
import random

class YearInfo (InterfaceElement):
	def init(s):
		s.eventhandlers = {
						'YEAR'			: s.setyear,
						'TIME'			: s.setyear
		}
	
	def init_vars(s):
		s.year = StringVar()
	
	def clear(s):
		s.year.set('')

	def draw(s, master):
		Label(master, text="Year:").pack(side=LEFT)
		Label(master, textvariable=s.year).pack(side=LEFT)
	
	def setyear(s, ev):
		s.year.set(ev.year)

class TransferInfo (InterfaceElement):
	def init(s):
		s.eventhandlers = {
						'tr_from'	: s.setfrom,
						'tr_to'		: s.setto,
						'tr_clear'	: s.clear
		}

	def init_vars(s):
		s.fromvar = StringVar()
		s.tovar = StringVar()
		s.distvar = StringVar()
		s.etavar = StringVar()
	
	def clear(s, ev=None):
		s.fromvar.set('')
		s.tovar.set('')
		s.distvar.set('')
		s.etavar.set('')

	def draw(s, master):
 		Label(master, text='Transfer').pack()
		frame = Frame(master)
		
		Label(frame, text='From:').grid(row=0, column=0, sticky=W)
		Label(frame, text='To:').grid(row=1, column=0, sticky=W)
		Label(frame, text='Dist:').grid(row=2, column=0, sticky=W)
		Label(frame, text='ETA:').grid(row=3, column=0, sticky=W)

		Label(frame, textvariable=s.fromvar).grid(row=0, column=1, sticky=W)
		Label(frame, textvariable=s.tovar).grid(row=1, column=1, sticky=W)
		Label(frame, textvariable=s.distvar).grid(row=2, column=1, sticky=W)
		Label(frame, textvariable=s.etavar).grid(row=3, column=1, sticky=W)

		frame.pack(anchor=W)		
	
	def setfrom(s, ev):
		pass

	def setto(s, ev):
		pass
	
	def calc(s):
		pass

class StatusBar (InterfaceElement):
	def init(s):
		s.eventhandlers = { 'status'	: s.set_status,
							'CLOK'		: s.clok
		}
	
	def init_vars(s):
		s.status = StringVar()
	
	def draw(s, master):
		l = Label(master, textvariable=s.status)
		l.pack(side=LEFT)
	
	def clear(s):
		s.status.set('')
	
	def set_status(s, ev):
		s.status.set(ev.cmd)
	
	def clok(s, ev):
		s.status.set("Client OK")

class Planet (SimpleInterfaceElement):
	def init(s):
		s.eventhandlers = {
							'PLNT' : 			s.plnt,
							'player_colour' :	s.player_colour
		}

	def init_vars(s):
		s.playfield = s.arg

	def draw(s, master):
		s.bmp = master.create_bitmap(0, 0, bitmap=s.playfield.planetbmp)
		s.text = master.create_text(0, 0, font=ClientDefaults.CanvasFont, text="")
		master.tag_bind(s.bmp, "<Enter>", s.selectplanet)
	
	def plnt(s, ev):
		s.id = ev.planet
		s.owner = ev.player
		s.x = ev.x
		s.y = ev.y
		x = s.x * s.playfield.pwidth + ClientDefaults.CanvasBorder + 1
		y = s.y * s.playfield.pheight + ClientDefaults.CanvasBorder + 1
		s.master.coords(s.bmp, x, y)
		s.master.coords(s.text, x, y)
		s.player_colour(ev)
		
	def selectplanet(s, ev):
		s.send_event(Event("selectplanet", planet=s.id))
	
	def player_colour(s, ev):
		colour = s.playfield.colour[s.owner]
		s.master.itemconfigure(s.bmp, foreground=colour)
		

class PlayField (InterfaceElement):
	def init(s):
		s.eventhandlers = {
			'PLNT' : 	s.plnt,
			'player_colour' :	s.player_colour
		}
	
	def init_vars(s):
		file = ClientDefaults.DataPath + ClientDefaults.PlanetBitmap
		bmp = BitmapImage(file=file)
		s.pwidth = bmp.width()
		s.pheight = bmp.height()
		s.planetbmp = "@" + file
		s.planets = {}
		s.colour = { 0 : 'black' }	
	
	def draw(s, master):
		s.canvas = Canvas(master, 	width=ClientDefaults.CanvasWidth, 
									height=ClientDefaults.CanvasHeight,
									background=ClientDefaults.CanvasBG)
		s.canvas.bind("<ButtonPress-1>", s.click)
		s.canvas.bind("<B1-Motion>", s.click)
		s.canvas.bind("<ButtonPress-3>", s.click)
		s.canvas.pack()
	
	def click(s, ev):
		pass
	
	def plnt(s, ev):
		try:
			planet = s.planets[ev.planet]
		except KeyError:
			planet = Planet(s.canvas, s, s.evq)
			s.planets[ev.planet] = planet
		planet.recv_event(ev)

	def player_colour(s, ev):
		s.colour[ev.player] = ev.name
		for p in s.planets.values():
			p.recv_event(ev)


class Player (SimpleInterfaceElement):
	def init(s):
		s.eventhandlers = { 'PLYR' :	s.plyr }
	
	def init_vars(s):
		s.name = StringVar()
		s.client = StringVar()
		s.done = StringVar()
		s.row = None
		s.colour = None
	
	def clear(s):
		s.name.set('')
		s.client.set('')
		s.done.set('')

	def draw(s, master):
		s.nlabel = Label(master, textvariable=s.name)
		s.clabel = Label(master, textvariable=s.client)
		s.dlabel = Label(master, textvariable=s.done)
		s.nlabel.bind('<Button-1>', s.change_colour)

	def update(s):
		if s.row == None:
			s.row = s.id - 1
			s.nlabel.grid(row=s.row, column=0, sticky=W)
			s.clabel.grid(row=s.row, column=1, sticky=W)
			s.dlabel.grid(row=s.row, column=2, sticky=W)
		if s.colour == None:
			s.change_colour()

	def plyr(s, ev):
		s.id = ev.player
		s.name.set(ev.name)
		s.client.set(string.join(ev.extra))
		s.update()

	def change_colour(s, ev=None):
		bright = random.randint(256, 512)
		rw = random.random()
		gw = random.random()
		bw = random.random()
		tot = rw + gw + bw
		unit = bright / tot
		r = min(rw * unit, 255)
		g = min(gw * unit, 255)
		b = min(bw * unit, 255)
		s.colour = "#%02x%02x%02x" % (r, g, b)
		ev = Event('player_colour', player=s.id, name=s.colour)
		s.send_event(ev)
		s.nlabel.configure(foreground = s.colour)		

class PlayerList (InterfaceElement):
	def init(s):
		s.eventhandlers = { 'PLYR' :	s.plyr }
	
	def init_vars(s):
		s.entries = {}
	
	def draw(s, master):
		Label(master, text="Players").pack()
		s.frame = Frame(master)
		s.frame.pack(anchor=W)
	
	def plyr(s, ev):
		try:
			player = s.entries[ev.player]
		except KeyError:
			player = Player(s.frame, s, s.evq)
			s.entries[ev.player] = player
		player.recv_event(ev)
			
class DoneButton (InterfaceElement):
	def init(s):
		s.eventhandlers = {
							'BRND' :	s.brnd,
		}
	
	def draw(s, master):
		s.button = Button(master, text="Turn Done", command=s.done, state=DISABLED)
		s.button.pack()
	
	def brnd(s, ev):
		s.button.configure(state=NORMAL)
	
	def done(s):
		s.button.configure(state=DISABLED)
		ev = Event("DONE")
		s.send_event(ev)
		
class MainMenu (InterfaceElement):
	def init(s):
		s.eventhandlers = {}

	def init_vars(s):
		s.qb = IntVar()
	
	def draw(s, master):
		s.menu = Menu(master)
		s.menu_game = Menu(s.menu, tearoff=0)
		s.menu_actions = Menu(s.menu, tearoff=0)
		s.menu_options = Menu(s.menu, tearoff=0)
		s.menu_game.add_command(label="Connect...", command=s.connect)
		s.menu_game.add_command(label="Disconnect", command=s.disconnect)
		s.menu_game.add_separator()
		s.menu_game.add_command(label="Quit", command=s.quit)
		s.menu_actions.add_command(label="Suicide", command=s.suicide)
		s.menu_options.add_checkbutton(label="QuickBattles", command=s.quickbattles, variable=s.qb)
		s.menu.add_cascade(label="Game", menu=s.menu_game)
		s.menu.add_cascade(label="Actions", menu=s.menu_actions)
		s.menu.add_cascade(label="Options", menu=s.menu_options)
		master.configure(menu=s.menu)
	
	def clear(s):
		s.qb.set(0)
		s.quickbattles()

	def connect(s):
		ev = Event('connect')
		s.send_event(ev)
	
	def disconnect(s):
		ev = Event("QUIT")
		s.send_event(ev)
	
	def quit(s):
		s.disconnect()
		s.master.quit()
	
	def quickbattles(s):
		ev = Event("quickbattles", flag=s.qb.get())
		s.send_event(ev)

	def suicide(s):
		ev = Event("SUIC")
		s.send_event(ev)

class Interface:
	def __init__(s, evq):
		s.evq = evq
		s.root = Tk()
		s.frameddisplaydefs = (
			( PlayField,	0,	0,	3,	1),
#			( Controls,		3,	0,	1,	1),
#			( Messages,		4,	0,	1,	1),
#			( MsgInput,		5,	0,	1,	1),
			( StatusBar,	6,	0,	1,	1),
			( PlayerList,	0,	1,	1,	1),
#			( Statistics,	1,	1,	1,	1),
			( TransferInfo,	2,	1,	1,	1),
#			( PlanetInfo,	3,	1,	2,	1),
			( YearInfo,		5,	1,	1,	1),
			( DoneButton,	6,	1,	1,	1)
		)
		s.otherdisplaydefs = (
			MainMenu,
			ConnectDialog,
			GameSelectDialog
		)
		s.frameddisplays = map(s.make_framed_display, s.frameddisplaydefs)
		s.otherdisplays = map(s.make_display, s.otherdisplaydefs)
		s.root.title(ClientDefaults.WindowTitle)
		s.root.columnconfigure(1, minsize=ClientDefaults.SidebarWidth)

	def start(s):
#		for d in s.frameddisplays:
#			d.start()
#		for d in s.otherdisplays:
#			d.start()
		s.root.mainloop()
	
	def make_display(s, handler):
		return handler(s.root, s.evq)

	def make_framed_display(s, args):
		handler, row, column, rowspan, columnspan = args
		f = Frame(s.root, borderwidth=1, relief=SUNKEN)
		f.grid(row=row, column=column, rowspan=rowspan, columnspan=columnspan, sticky=W+E+N+S, padx=1, pady=1)
		h = handler(f, s.evq)
		return h
	
			