from Tkinter import *
from ClientEvent import SimpleInterfaceElement, InterfaceElement, Event
import ClientDefaults
import string

class Dialog (InterfaceElement):
	"Base class for dialog boxes."

	title = ''
	text_ok	= 'OK'
	text_cancel = 'Cancel'
	grab = 1
	place = 1

	def display(s, ev=None):
		s.top = Toplevel(s.master)
		s.top.transient(s.top)
		if s.place:
			s.top.geometry("+%d+%d" % (s.master.winfo_rootx() + 50,
									   s.master.winfo_rooty() + 50))
		
		if s.title:
			s.top.title(s.title)
		
		body = Frame(s.top)
		s.initial_focus = s.body(body)
		body.pack(padx=5, pady=5)
		
		s.buttonbox()
		
		if s.grab:
			try:
				s.top.grab_set()
			except TclError:
				pass
		
		if not s.initial_focus:
			s.initial_focus = s.top
		
		s.top.protocol("WM_DELETE_WINDOW", s.cancel)
		
		s.initial_focus.focus_set()
		
	def hide(s, ev=None):
		s.top.destroy()
		s.master.focus_set()
		s.top.destroy()

	def body(s, master):
		"Create the dialog body. Should be overridden."
		
		pass
	
	def buttonbox(s):
		"Create the button box."
		
		box = Frame(s.top)
		
		b1 = Button(box, text=s.text_ok, width=10, command=s.ok, default=ACTIVE)
		b1.pack(side=LEFT, padx=5, pady=5)
		if s.text_cancel:
			b2 = Button(box, text=s.text_cancel, width=10, command=s.cancel)
			b2.pack(side=LEFT, padx=5, pady=5)
		
		s.top.bind("<Return>", s.ok)
		if s.text_cancel:
			s.top.bind("<Escape>", s.cancel)
		
		box.pack()
	
	def ok(s, event=None):
		"The OK button has been pressed."

		if not s.validate():
			s.initial_focus.focus_set()
			return
		
		s.top.withdraw()
		s.apply()
		s.hide()
	
	def cancel(s):
		"The Cancel button has been pressed."
		s.hide()
		
	def validate(s):
		"Should probably be overridden. Check that the data is OK."

		return 1
	
	def apply(s):
		"Override this."

		pass

class GameListEntry (SimpleInterfaceElement):
	def init(s):
		s.eventhandlers = {
						'GAME'	: s.game
		}

	def init_vars(s):
		s.button = None
		s.text = StringVar()
	
	def game(s, ev):
		s.id = ev.game
		s.owner = ev.player
		s.name = ev.name
		s.nplayers = len(ev.extra)
		s.players = string.join(ev.extra, ', ')
		if not s.button:
			s.button = Radiobutton(s.master, textvariable=s.text, variable=s.arg, value=s.id)
			s.button.grid(row=s.id, column=0, sticky=W)
		str = "Game %s, %d players: %s" % (s.id, s.nplayers, s.players)
		s.text.set(str)

class GameList (SimpleInterfaceElement):
	def init(s):
		s.eventhandlers = {
						'GAME'	: s.game
		}
	
	def init_vars(s):
		s.entries = {}
		s.choice = IntVar()
	
	def game(s, ev):
		try:
			game = s.entries[ev.game]
		except KeyError:
			game = GameListEntry(s.master, s.choice)
			s.entries[ev.game] = game
		game.recv_event(ev)

class GameSelectDialog (Dialog):
	title = 'Select Game'

	def init(s):
		s.eventhandlers = {
							'BGML' :	s.display,
							'GAME' :	s.game
		}

	def init_vars(s):
		s.games = {}
		s.name = StringVar()
	
	def clear(s):
		s.name.set(ClientDefaults.PlayerName)
	
	def body(s, master):
		Label(master, text="Select the game to join").pack()
		f1 = Frame(master)
		s.list = GameList(f1)
		f1.pack()
		f2 = Frame(master)
		Label(f2, text="Player Name:").pack(side=LEFT)
		Entry(f2, textvariable=s.name).pack(side=LEFT)
		f2.pack(padx=5, pady=5)
	
	def apply(s):
		choice = s.list.choice.get()
		name = s.name.get()
		ev = Event('JOIN', game=choice, name=name)
		s.send_event(ev)
	
	def game(s, ev):
		s.list.recv_event(ev)

class ConnectDialog (Dialog):
	title = 'Connect to Server'

	def init(s):
		s.eventhandlers = { 'connect' : s.display }

	def init_vars(s):
		s.host = StringVar()
		s.port = StringVar()
	
	def clear(s):
		s.host.set(ClientDefaults.ServerHost)
		s.port.set(ClientDefaults.ServerPort)
	
	def body(s, master):
		Label(master, text="Connect to server").grid(columnspan=2)
		Label(master, text="Host:").grid(row=1, column=0)
		Label(master, text="Port:").grid(row=2, column=0)
		Entry(master, textvariable=s.port).grid(row=2, column=1)
		return Entry(master, textvariable=s.host).grid(row=1, column=1)
	
	def apply(s):
		host = s.host.get()
		port = string.atoi(s.port.get())
		ev = Event('connect_to', name=host, quant=port)
		s.send_event(ev)
	
	def validate(s):
		try:
			port = string.atoi(s.port.get())
			return s.host.get()
		except ValueError:
			return 0