#!/usr/bin/python
#
#	released under the terms of the GPL v 2.0 (or later, at your opinion)
#	(c) 2005,2006 Roland Lezuo <roland.lezuo@chello.at>
#

# XXX we should create a class GameGnugo
# 		     Game 
#         ^    ^
# 	     /		  \ 
#  GameGnugo   GameHuman
		

__author__ = "Roland Lezuo <roland.lezuo@chello.at>"

import logging
logger = logging.getLogger("gnomego")

import gnomego.gtp
import os, sys, traceback
import gtk, gtk.glade, pango
import gnome, gnome.ui, gconf
import gettext
import gnomego.board
import gnomego.preferences
import thread

# class Game is a small abstraction over the gtp protocoll
# no clean design can be seen in here so don't try it
class Game:
	# call this with path to gnugo and parameters it may need
	def __init__(self, program, callback):
		if program == None: 
			raise "New Game with None program"
		self._gtp = gnomego.gtp.gtp(program, self._moved)
		self._callback = callback
		self._lock = thread.allocate_lock()

	def _unlock_on_exception(self, func, *args):
		try:
			return self._gtp.__class__.__dict__[func](self._gtp, *args)
		except:
			self._lock.release()
			logger.warning("Game._unlock_on_exception has thrown")
			raise


	def actualColor(self):
		# makes only sense in multiplayer mode
		return gettext.gettext('black')	

	def newGame(self, boardsize, komi, iAmBlack, level, handicap, human):
		self._lock.acquire()
		self._set_color(iAmBlack)
		self._unlock_on_exception('setBoardsize', boardsize)
		self._unlock_on_exception('clearBoard')
		self._unlock_on_exception('setKomi', komi)
		self._unlock_on_exception('setHandicap', handicap)
		self._unlock_on_exception('level', level)

		# caches data queried while the lock is hold
		self._bscache = []	# position of black stones
		self._wscache = []	# position of white stones
		self._mhcache = {}	# full game history
		self._wccache = 0	# number of stones captured by white
		self._bccache = 0	# number of stones captured by black
		self._sccache = 'error'	# the final score

		self._passed = False
		self._komi = komi
		self._game_over = False
		self._resigned = False

		if handicap < 2: 
			if iAmBlack and not human:
				logger.info('Player is black and gets first move, no handicap')
				self._turn = 'b'	# it's black turn in the beginning
				self._lock.release()
			elif not human:
				logger.info('Gnugo is black and gets first move, no handicap')
				self._turn = 'g'
				self._unlock_on_exception('genmove', self._othercolor)
			else: 
				logger.info('human vs human without handicap')
				self._mycolor = 'w'
				self._othercolor = 'b'
				self._turn = 'b'
				self._lock.release()
		else: 
			#if its hum vs. hum
			if human: 
				logger.info('human vs human with handicap')
				self._mycolor = 'w'
				self._othercolor = 'b'
				self._turn = 'w'
				self._lock.release()
			else:
				if iAmBlack and not human:
					logger.info('Player is black and gets the second move, with handicap')
					self._turn = 'g'	# it's gungos turn now, let it think...
					#TODO self._lock.acquire()	# when to acuire lock? makes pref window lock
					self._unlock_on_exception('genmove', self._othercolor)
				elif not human:
					logger.info('Gnugo is black and gets the second move, with handicap')
					self._turn = 'w'	# it's whites turn in the beginning of a handicap game
					self._lock.release()
	

	def _set_color(self, iAmBlack):
		if iAmBlack:
			self._mycolor = 'b'
			self._othercolor = 'w'
		else:
			self._mycolor='w'
			self._othercolor='b'
	def _move(self, mymove):
		self._passed = False
		self._unlock_on_exception('move', self._mycolor, mymove)
		# update the caches used to draw the board and place add the stone
		if self._turn == 'b':
			self._bscache.append(self._stones_to_list(mymove)[0])
		else:
			self._wscache.append(self._stones_to_list(mymove)[0])
		# genmove sets up a callback handler, we will be called back as soon as gnugo moves!
		self._last_move = mymove
		self._last_color = self._mycolor
		self._turn = 'g'
		self._unlock_on_exception('genmove', self._othercolor)

	# when the player puts a stone, returns True if putting stone was a success
	def put_stone(self, x, y):
		if self.get_player_state() == 'g':
			# not ready for user input, gnugo is still thinking
			return False

		# no more stones if we are already done
		if self._game_over: 
			raise RuntimeError(gettext.gettext('Game is over already'))	# XXX: is it good to use RuntimeError? gnomego.gtp does so too

		self._lock.acquire()

		# player passed
		if x == -1 and y == -1:
			self._passmove()
			return True

		# for some reason there is no column I(i) on a go board, I is simply left out, well, so do we :)
		x_chr = chr(ord('A') + x - 1)
		if ord(x_chr) >= ord('I'):
			x_chr = chr(ord(x_chr) + 1)
		# make the move
		move = x_chr + str(y)
		self._move(move)
		return True

	# returns one of three characters
	# 'b' if waiting for blacks turn
	# 'w' if waiting for whites turn
	# 'g' if gnugo is still thinking
	def get_player_state(self):
		return self._turn
	
	# let gnugo play a move, important, after loading games
	def triggerMove(self, iAmBlack):
		pass
		self._set_color(iAmBlack)
		self._passed = False
		res = self._gtp.genmove_blocking(self._othercolor)
		self._moved_blocking(res)
	
	def _passmove(self):
		self._turn = 'g'	# it's gungos turn now, let it think...
		self._passed = True
		self._unlock_on_exception('passmove', self._mycolor)
		self._last_color = self._mycolor
		self._last_move = 'PASS'
		self._unlock_on_exception('genmove', self._othercolor)

	# returns [(x,y)] with all white/black stones on the board
	# do not block when we are waiting for a callback but return cached results instead
	def get_white_stones(self):
		if self._lock.acquire(False):
			l = self._unlock_on_exception('listStones' ,'w')
			self._lock.release()
			self._wscache = self._stones_to_list(l)
		return self._wscache

	def get_black_stones(self):
		if self._lock.acquire(False):
			l = self._unlock_on_exception('listStones', 'b')
			self._lock.release()
			self._bscache = self._stones_to_list(l)
		return self._bscache

	def _stones_to_list(self, l):
		ret = []
		if l == 'PASS': 
			return [(0,0)]
		for w in l.split():
			c = w[0]
			n = w[1:]
			if ord(c) >= ord('J'):
				c = ord(c) - 1 - ord('A')
			else:
				c = ord(c) - ord('A')
			n = int(n) - 1
			ret.append((int(c), n))
		return ret

	def get_move_history(self):
		if self._lock.acquire(False):
			moves = self._unlock_on_exception('getMoveHistory')
			self._lock.release()
			m = moves.replace('black','').replace('white','').split()
			m.reverse()
			c = 1
			d = {}
			for i in m:
				if i != 'PASS':
					i = self._stones_to_list(i)[0]
					if d.has_key(i):
						d[i].append(c)
					else:
						d[i] = [c]
				c += 1
			self._mhcache = d
		return self._mhcache
	# this one will be called when GnuGO moved
	def _moved(self, fd, cb_cond):
		#read the result
		self._last_move = self._gtp.rx()
		self._last_color = self._othercolor
		self._turn = self._mycolor
		
		# update the caputes counters
		self._bccache = self._gtp.getCaptures('black')
		self._wccache = self._gtp.getCaptures('white')

		logger.debug("Game._moved: " + str(self._last_move))
		self._moved_blocking(self._last_move)
		self._lock.release()
		self._callback()
		return False
	# just delgate work to moved_blocking
	def _moved_blocking(self, result):
		if result == 'PASS' and self._passed:
			# the game is over NOW!
			board.game_is_over()
			board.set_default_cursor()
			self._game_over = True
			self._sccache = self._unlock_on_exception('finalScore')
		if result == 'resign':
			logger.info("GnuGo resigned")
			board.game_is_over()
			board.set_default_cursor()
			self._game_over = True
			self._resigned = True
			if self._turn == 'w':
				self._sccache = "W+R"
			else:
				self._sccache = "B+R"
		return False
	# returns the last move done by gnugo
	# as tuple in string format and coordinates
	def get_last_move(self):
		return self._last_move, self._stones_to_list(self._last_move)[0]
	# and the color of the last stone which has been put by gnugo
	def get_last_color(self):
		return self._last_color


	# returns the final score in format W+1.5
	def get_final_score(self):
		return self._sccache

	# returns the state of all fields, better said lists af fields in certain states
	def get_final_status(self):
		if self._resigned:
			# in case someone resigned do not try to let gnugo calculate anything, would durate forever
			return {'alive':self._wscache + self._bscache, 'dead':[], 'seki':[], 'white_territory':[], 'black_territory':[], 'dame':[]}
		self._lock.acquire()
		try:
			alive = self._stones_to_list(self._gtp.finalStatus('alive'))
			dead = self._stones_to_list(self._gtp.finalStatus('dead'))
			seki = self._stones_to_list(self._gtp.finalStatus('seki'))
			white_territory = self._stones_to_list(self._gtp.finalStatus('white_territory'))
			black_territory = self._stones_to_list(self._gtp.finalStatus('black_territory'))
			dame = self._stones_to_list(self._gtp.finalStatus('dame'))
		except:
			self._lock.release()
			raise
		self._lock.release()
		return {'alive':alive, 'dead':dead, 'seki':seki, 'white_territory':white_territory, 'black_territory':black_territory, 'dame':dame}
	# returns a nice string of the caps
	# this method is non blocking
	def get_captures(self):
		return '[' + str(self._bccache) +':' + str(float(self._komi) + float(self._wccache)) + ']'

	def undo(self):
		# undo players and gnugos move
		self._gtp.undo()
		self._gtp.undo()
		self._game_over = False
		self._resigned = False

	def redo(self):
		pass

	def save(self, filename):
		self._gtp.save(filename)

	# load a sgf file and return (boardsize, komi, blackplayerstrunboolean)
	def load(self, filename):
		try:
			pl = self._gtp.load(filename)
		except:
			raise
		k = self._gtp.getKomi()
		b = self._gtp.getBoardsize()
		return (b, k, pl == 'black')
	def get_game_over(self):
		return self._game_over


# some subclassing
class GameHuman(Game):
	def _move(self, mymove):
		self._passed = False
		self._unlock_on_exception('move', self._turn, mymove)
		# update the caches used to draw the board and place add the stone
		if self._turn == 'b':
			self._bscache.append(self._stones_to_list(mymove)[0])
		else:
			self._wscache.append(self._stones_to_list(mymove)[0])

		self._bccache = self._gtp.getCaptures('black')
		self._wccache = self._gtp.getCaptures('white')

		self._switch_color()
		self._last_move = mymove
		self._last_color = self._turn
		self._lock.release()
		self._callback()

	def _passmove(self):
		if self._passed:
			self._game_over = True
			self._sccache = self._unlock_on_exception('finalScore')
			board.game_is_over()
			board.set_default_cursor()
		else:
			self._passed = True
			self._unlock_on_exception('passmove', self._turn)
			self._switch_color()
		self._last_move = 'PASS'
		self._lock.release()
		self._callback()

	def undo(self):
		self._gtp.undo()
		self._game_over = False
		self._switch_color()

	def _switch_color(self):
		if self._turn == 'b':
			self._turn = 'w'
		else:
			self._turn = 'b'



# handling the events of the various elements
class GladeHandlers:
	signales_triggered_by_me = False
	def on_quit1_activate(self):
		sys.exit(0)
	def on_help1_activate(self):
		print 'help'
		gnome.help_display('/usr/share/gnome/help/gnomego/gnomego.xml')
	def on_new2_activate(self):
		pref = gnomego.preferences.GnomeGoPref()
		# here is the only point where a newGame call is made, so filter bad values here
		# TODO: better move the default value init stuff somewhere else
		
		size = pref.get_int('size')
		level = pref.get_int('level')
		boardimg = pref.get_string('boardimg')
		boardcolor_str = pref.get_string('boardcolor')
		scale = pref.get_float('scale')
		cmd = pref.get_string('cmd')
		vshuman = pref.get_bool('vshuman')
		movenumber = pref.get_bool('movenumber')
		showcoords = pref.get_bool('showcoords')
		komi = pref.get_float('komi')
		iAmBlack = not pref.get_bool('gnugo_is_black')
		logger.info('gnugo_is_black from config as %s' % (not iAmBlack))
		handicap = pref.get_int('handicap')
		if handicap == None: 
			handicap = 0
		if (size == 9) and (handicap > 5): 
			handicap = 5
	
		boardcolor = None
		try:
			boardcolor = gtk.gdk.color_parse(boardcolor_str)
		except:
			print "Exception on_new2_activate: boardcolor"
			pass
	
		game.newGame(size, komi - 1, iAmBlack, level, handicap, vshuman)
		global board
		pango_ctx = gui.get_widget('drawingarea1').get_pango_context()
		board = gnomego.board.Board(gui.get_widget('drawingarea1').window, game, size, scale, vshuman, movenumber, True, pango_ctx, pref.installed_prefix)
		board.set_background_image(boardimg)
		board.set_background_color(boardcolor)
		statusbar.push(1, gettext.gettext('New game started, komi is ') + str(komi - 1))
		gui.get_widget('drawingarea1').set_size_request(*board.get_size())
		board.redraw()

	def on_preferences1_activate(self):
		# before showing the window preload its properties
		pref = gnomego.preferences.GnomeGoPref()
		size = pref.get_int('size')
		level = pref.get_int('level')
		boardimg = pref.get_string('boardimg')
		boardcolor_str = pref.get_string('boardcolor')
		scale = pref.get_float('scale')
		cmd = pref.get_string('cmd')
		vshuman = pref.get_bool('vshuman')
		movenumber = pref.get_bool('movenumber')
		showcoords = pref.get_bool('showcoords')
		komi = pref.get_float('komi')
		handicap = pref.get_int('handicap')

		if cmd != None and len(cmd) != 0: gui.get_widget('gnugo_entry').set_text(cmd)
		if boardimg != None and len(boardimg) != 0: 
			# check if we are using a default image, and if so adjust combobox according
			if boardimg.startswith(pref.installed_prefix + 'board'):
				# yes it seems so
				img_number = boardimg[len(pref.installed_prefix) + len('board')]
				try:
					i = int(img_number)
					gui.get_widget('texture').set_active(i)
				except:
					# well no, was not...
					pass

			gui.get_widget('boardimg_entry').set_text(boardimg)

		if level != 0: 
			gui.get_widget('level_entry').set_text(str(level))
		else:
			gui.get_widget('level_entry').set_text('10')
	
		GladeHandlers.signales_triggered_by_me = True
		if size == 9:
			gui.get_widget('9x9').set_active(True)
		elif size == 13:
			gui.get_widget('13x13').set_active(True)
		else:
			# 19 is the default size, therefore!
			gui.get_widget('19x19').set_active(True)	

		if handicap == None: 
			handicap = 0
		act_hcp = 0
		if handicap > 0: 
			act_hcp = handicap-1
		gui.get_widget('handicap').set_active(act_hcp)

		try:
			gui.get_widget('scale').set_value(scale)
			gui.get_widget('color').set_color(gtk.gdk.color_parse(boardcolor_str))
		except:
			print "Exception setting scale/color"
			pass
		GladeHandlers.signales_triggered_by_me = False
		GladeHandlers.__dict__['on_color_color_set']('foo')	# trigger color change event, for some reason the bakcground is black else...FIXME
	
		gui.get_widget('preferences').show()

	def on_size_change(self, *arg):
		if GladeHandlers.signales_triggered_by_me: return
		aply_preferences()
		GladeHandlers.__dict__['on_new2_activate'](None)

	def on_handicap_change(self, *arg):
		if GladeHandlers.signales_triggered_by_me: return
		aply_preferences()
		GladeHandlers.__dict__['on_new2_activate'](None)

	def on_scale_value_changed(self, *args):
		global board
		scale = gui.get_widget('scale').get_value()
		board.set_scale(scale)
		gui.get_widget('drawingarea1').set_size_request(*board.get_size())
		board.redraw()
	
	def on_texture_changed(self, *args):
		sel = gui.get_widget('texture').get_active()
		if sel == 0:
			# we use a plain background color
			gui.get_widget('boardimg_entry').set_text('_')
		else:
			gui.get_widget('boardimg_entry').set_text(gnomego.preferences.GnomeGoPref().installed_prefix +'board' + str(sel) + '.png')


	def on_color_color_set(self, *args):
		if GladeHandlers.signales_triggered_by_me: return
		global board
		board.set_background_color(gui.get_widget('color').get_color())
		board.redraw()

	def on_buttonOpenFile_clicked(self, *args):
		print "OPEN"
		fcd = gtk.FileChooserDialog(action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
		fcd.set_modal(True)
		f = gtk.FileFilter()
		f.set_name(gettext.gettext("Images"))
		f.add_mime_type("image/*")
		fcd.add_filter(f)
		res = fcd.run()

		if res == gtk.RESPONSE_OK:
			fn = fcd.get_filename()
			gui.get_widget('boardimg_entry').set_text(fn)
			print "set image"
		else:
			print "cancle"
		fcd.destroy()

	def on_boardimg_entry_changed(self, *args):
		img = gui.get_widget('boardimg_entry').get_text()
		print img
		global board
		board.set_background_image(img)
		board.redraw()

	def on_about1_activate(self):
		about = gnome.ui.About(prog_name, prog_version, '(C) 2005 Roland Lezuo', gettext.gettext('A simple but nice gnuGo GUI'), 
			['Roland Lezuo <roland.lezuo@chello.at>'], None, 
				u'Roland Lezuo <roland.lezuo@chello.at>\n' +
				u'SZERV\xd1C Attila <sas@321.hu>\n' + 
				u'Erdogan Karabicak <erdogankarabicak@yahoo.com>\n'
			, gtk.gdk.pixbuf_new_from_file(gnomego.preferences.GnomeGoPref().installed_prefix + 'gnomego_64x64.png'))
		about.show()
		#gui.get_widget('dialog3').show()
	def on_drawingarea1_button_press_event(self, ev):
		pos = board.get_stone_coordinates(int(ev.x), int(ev.y))
		if pos != None:
			try:
				if game.put_stone(*pos):
					GladeHandlers.__dict__['on_stone_put_event']()

			except RuntimeError, mess:
				statusbar.push(1, str(mess))


	def on_drawingarea1_expose_event(self, ev):
		GladeHandlers.__dict__['on_stone_put_event']()
	def on_stone_put_event():
		if not board: 
			return
		p = game.get_player_state()
		if p == 'w':
			board.set_white_cursor()
		elif p == 'b':
			board.set_black_cursor()
		else:
			board.set_default_cursor()
		# update the status bar
		# but we may be in a state where still no move has been done
		# catch these exceptions silently
		try:
			movestr,move = game.get_last_move()
			c = game.get_last_color()
			if c == 'w':
				color = 'white'
			elif c == 'b':
				color = 'black'
			else:
				color = 'error'
			r = game.get_captures()
			statusbar.push(1, gettext.gettext(color + ':') + movestr + ' ' + r)
			# additionally mark the last put stone
			board.clear_marks()
			if movestr != 'PASS': board.mark_stone(move)
			
		except:
			pass

		# everything is a little bit different if the game is over alread
		if game.get_game_over():
			r = game.get_final_score()
			statusbar.push(1, gettext.gettext('result') + ': ' + r)
			board.clear_marks()
			board.set_default_cursor()

		board.redraw()

	def on_window1_destroy(self):
		sys.exit(0)

	def on_preferences_delete_event(self, arg):
		# prevent deletion of the widget, cause I don't know how to recreate it :)
		return True
	# the about dialog
	def on_dialog3_delete_event(self, arg):
		return True
	def on_dialog3_response(self, arg):
		self.hide()

	def on_preferences_response(self, arg):
		aply_preferences()
		# and hide
		self.hide()

	def on_gnugoblack1_activate(self, *arg):
		if GladeHandlers.signales_triggered_by_me: return
		global game
		current_gnugo_color = gnomego.preferences.GnomeGoPref().get_bool('gnugo_is_black')
		gnomego.preferences.GnomeGoPref().set_bool('gnugo_is_black', not current_gnugo_color)
		logger.info('on_gnugoblack1_activet(): setting gnugo_is_black to %s' % (not current_gnugo_color)) 	
		if gnomego.preferences.GnomeGoPref().get_bool('vshuman'):
			game = GameHuman(nameofthegame, GladeHandlers.__dict__['on_stone_put_event'])
		else:
			game = Game(nameofthegame, GladeHandlers.__dict__['on_stone_put_event'])
		gui.get_widget('new2').activate()	# starts a new game
		
	def on_vs_gnugo_activate(self, *arg):
		global game
		gnomego.preferences.GnomeGoPref().set_bool('vshuman', False)
		game = Game(nameofthegame, GladeHandlers.__dict__['on_stone_put_event'])
		gui.get_widget('new2').activate()	# starts a new game
	def on_vs_human_activate(self, *arg):
		global game
		gnomego.preferences.GnomeGoPref().set_bool('vshuman', True)
		game = GameHuman(nameofthegame, GladeHandlers.__dict__['on_stone_put_event'])
		gui.get_widget('new2').activate()	# starts a new game
	def on_undo1_activate(self, *args):
		global game
		global statusbar
		try:
			game.undo()
		except:
			#may happen if no stone to undo
			statusbar.push(1, gettext.gettext('nothing to undo'))
			return

		global board
		c = game.get_player_state()
		if c == 'b':
			board.set_black_cursor()
		elif c == 'w':
			board.set_white_cursor()
		else:
			board.set_default_cursor()

		statusbar.push(1, gettext.gettext('move undone'))
		board.undo_game_is_over()
		board.clear_marks()
		board.redraw()

	def on_save_as1_activate(self, *args):
		global game
		fcd = gtk.FileChooserDialog(action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK))
		fcd.set_modal(True)
		fcd.set_current_name(".sgf")
		res = fcd.run()
		if res == gtk.RESPONSE_OK:
			filename = fcd.get_filename()
			game.save(filename)
		fcd.destroy()

	def on_open1_activate(self, *args):
		fcd = gtk.FileChooserDialog(action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
	
		fcd.set_modal(True)
		f = gtk.FileFilter()
		f.set_name(gettext.gettext("SGF files"))
		f.add_pattern("*.sgf")
		fcd.add_filter(f)
		f = gtk.FileFilter()
		f.set_name(gettext.gettext("All files"))
		f.add_pattern("*")
		fcd.add_filter(f)
		res = fcd.run()

		if res == gtk.RESPONSE_OK:
			global game
			global board
			fn = fcd.get_filename()
			fcd.destroy()
			try:
				(size, komi, blacksturn) = game.load(fn)
			except:
				err = gnome.ui.error_dialog(gettext.gettext('Could not load file (be sure name contains no space, # or control characters)'))
				err.run()
				return

			pref = gnomego.preferences.GnomeGoPref()

			scale = pref.get_float('scale')
			human = pref.get_bool('vshuman')
			moven = pref.get_bool('movenumber')
			showcoords = pref.get_bool('showcoords')
			boardimg = pref.get_string('boardimg')
			boardcolor = pref.get_string('boardcolor')


			pango_ctx = gui.get_widget('drawingarea1').get_pango_context()
			board = gnomego.board.Board(gui.get_widget('drawingarea1').window, game, int(size), scale, human, moven, True, pango_ctx, pref.installed_prefix)
			board.set_background_image(boardimg)
			try:
				board.set_background_color(gtk.gdk.color_parse(boardcolor))
			except:
				pass
			gui.get_widget('drawingarea1').set_size_request(*board.get_size())
			board.redraw()
			statusbar.push(1, gettext.gettext('Loaded game, komi is ') + str(komi))

			if blacksturn:
				board.set_black_cursor()
			else:
				if board.multiplayer:
					board.set_white_cursor()
				else:
					# hardcoded: player is black XXX
					game.triggerMove(True)
		else:
			fcd.destroy()

	def on_move_numbers_activate(self, *args):
		global board
		state = gui.get_widget('move_numbers').get_active()
		gnomego.preferences.GnomeGoPref().set_bool('movenumber', state)
		if board:
			board.set_movenumbers(state)
			board.redraw()
	
	def on_display_coordinates1_activate(self, *args):
		global board
		state = gui.get_widget('display_coordinates1').get_active()
		gnomego.preferences.GnomeGoPref().set_bool('showcoords', state)
		if board:
			board.set_showcoords(state)
			board.redraw()

	def on_pass1_activate(self, *args):
		if game.put_stone(-1,-1):
			GladeHandlers.__dict__['on_stone_put_event']()
		


def aply_preferences():
	# fetch the data and store it using gconf
	pref = gnomego.preferences.GnomeGoPref()

	cmd = gui.get_widget('gnugo_entry').get_text()
	boardimg = gui.get_widget('boardimg_entry').get_text()
	level = gui.get_widget('level_entry').get_text()
	gnugo_is_black = gui.get_widget('gnugoisblack').get_active()
	handicap = gui.get_widget('handicap').get_active_text()	
	if handicap == None: handicap = 0

	# board size
	if gui.get_widget('9x9').get_active():
		pref.set_int('size', 9)
	elif gui.get_widget('13x13').get_active():
		pref.set_int('size', 13)
	elif gui.get_widget('19x19').get_active():
		pref.set_int('size', 19)
	else:
		# should never happen
		print 'aply_changed should never happen just happened'
		pass

	#board scale
	scale = gui.get_widget('scale').get_value()
	pref.set_float('scale', scale)

	#board backgroundcolor
	color = gtk.color_selection_palette_to_string([gui.get_widget('color').get_color()])
	pref.set_string('boardcolor', color)

	# gnugo commandline
	pref.set_string('cmd', cmd)
	
	# path to background image
	pref.set_string('boardimg', boardimg)	

	# gnugo strength
	pref.set_int('level', int(level))	
	
	# handicap
	pref.set_int('handicap', int(handicap))	

# finally, the startup code

def main():
	if os.getenv("GNOMEGO_DEBUG") != None:
		logging.basicConfig(level=logging.DEBUG)
	else:
		logging.basicConfig()

	global nameofthegame
	p = gnomego.preferences.GnomeGoPref()
	nameofthegame = p.get_string('cmd')

	# figure out the program version
	global prog_version
	prog_version = p.get_string('version')

	# sanity check nameofthegame
	gnugo = ""
	try:
		# try some commuincation with the program, we will see then...
		test = gnomego.gtp.gtp(nameofthegame, None)
		gnugo = test.name()
		
	except:
		# can't be good, better use defaultvalue
		print 'NameOfTheGame fallback to default: ' + str(nameofthegame) + ' could not be used!'
		nameofthegame = p.nameofthegame_default

	
		# and try again, why I can't use a finally and an except together ??
		try:
			test = gnomego.gtp.gtp(nameofthegame, None)
			gnugo = test.name()
		except:
			print 'No gnuGo found, sorry'
			err = gnome.ui.error_dialog(gettext.gettext('The required program gnugo can''t be found in $PATH'))
			err.run()
			sys.exit(1)
	logger.debug(gnugo)
	if gnugo == 'GNU Go 3.6':
		#Thilo Pfenning reported gnomego hangs on gnugo 3.6
		print 'Gnu Go 3.6 is reported to block gnomego forever, please upgrade to 3.7'
		err = gnome.ui.error_dialog(gettext.gettext('The required program gnugo is too old, please use at least 3.7'))
		err.run()
		sys.exit(1)

	global gui
	gui = gtk.glade.XML(p.installed_prefix + 'gnomego.glade')
	gui.signal_autoconnect(GladeHandlers.__dict__)

	# set up globals
	global statusbar
	statusbar = gui.get_widget('statusbar1')

	global board 
	board = None 

	moven = p.get_bool('movenumber')
	if moven:
		gui.get_widget('move_numbers').set_active(True)
	else:
		gui.get_widget('move_numbers').set_active(False)

	showcoords = p.get_bool('showcoords')
	if showcoords:
		gui.get_widget('display_coordinates1').set_active(True)
	else:
		gui.get_widget('display_coordinates1').set_active(False)

	#handicap = p.get_int('handicap')
	#if handicap == None: handicap = 0
	#act_hcp = 0
	#if handicap > 0: act_hcp = handicap-1
	#gui.get_widget('handicap').set_active(act_hcp)

	human = p.get_bool('vshuman')
	# have to set the menu anyway, and the menu action handlers create the new Games and start them
	if human:
		gui.get_widget('vs_gnugo').set_active(False)
		gui.get_widget('vs_human').set_active(True)
		gui.get_widget('vs_human').activate()
	else:
		gui.get_widget('vs_gnugo').set_active(True)
		gui.get_widget('vs_human').set_active(False)
		gui.get_widget('vs_gnugo').activate()
	
	handler_state = GladeHandlers.signales_triggered_by_me		
	GladeHandlers.signales_triggered_by_me = True
	gnugo_is_black = p.get_bool('gnugo_is_black')
	if gnugo_is_black:
		gui.get_widget('gnugoisblack').set_active(True)
	else:
		gui.get_widget('gnugoisblack').set_active(False)
	GladeHandlers.signales_triggered_by_me	= handler_state

	gtk.main()

# global vars
prog_name = 'GnomeGo'
prog_version = '0.0'
statusbar = None
game = None
gui = None
board = None
nameofthegame = None

# will be set to correct pathed when installed


try:
	if __name__ == '__main__': 
		# initialze gnome app and gettext support
		gnome.program_init(prog_name, prog_version)
		gettext.textdomain('gnomego')
		gtk.glade.textdomain('gnomego')
		main()
except RuntimeError, str:
	print 'Fatal RuntimeError occured!'
	print str
except:
	print 'Fatal Exception occured!'
	print traceback.print_exc()
	sys.exit(1)
