#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Client for the Chinese Chess game
# Copyright (C) 2004 - 2006 Josef Spillner <josef@ggzgamingzone.org>
# Published under GNU GPL conditions

import pygame
import pygame.image
from pygame.locals import *
from Numeric import *
import sys
import time
import random
import os, pwd
import re

import ggzmod
import sdlnewstuff

try:
	import ggzsettings
	DATAPATH = ggzsettings.DATAPATH + "/xadrez-chines/"
	sys.path = [ggzsettings.MODULEPATH + "/xadrez-chines/"] + sys.path
	sys.path = [ggzsettings.MODULEPATH + "/common/"] + sys.path
except:
	DATAPATH = "./"
	sys.path = ["../lib/"] + sys.path

import playertable
from xadrezlib import *

def unic(s):
	return unicode(s, "utf-8")

print unic("Xadrez Chinês: Using data path"), DATAPATH

def homedir():
	return pwd.getpwuid(os.geteuid())[5]

def networkprocess(line):
	global madeturn
	global humanerror
	global message
	global winner
	global xadrez
	global aierror

	print "LINE", line

	turn = re.compile("your turn")
	responseok = re.compile("move was ok")
	responseinvalid = re.compile("move was invalid")
	responseturn = re.compile("not your turn")
	move = re.compile("(\S+) moved from (\d+),(\d+) to (\d+),(\d+)")
	event = re.compile("(\S+) took figure at (\d+),(\d+) from (\S+)")
	gameover = re.compile("(\S+) won")

	m = turn.match(line)
	if m:
		madeturn = 0
		message = "It's your turn"
	m = responseok.match(line)
	if m:
		humanerror = 0
		madeturn = 1
		message = ""
	m = responseinvalid.match(line)
	if m:
		humanerror = 1
	m = responseturn.match(line)
	if m:
		pass
	m = move.match(line)
	if m:
		player = m.group(1)
		x1 = int(m.group(2))
		y1 = int(m.group(3))
		x2 = int(m.group(4))
		y2 = int(m.group(5))
		ret = xadrez.validate(x1, y1, x2, y2)
		if ret != xadrez.proto.move_ok:
			print "huh? server fubared"
			aierror = 1
	m = event.match(line)
	if m:
		player = m.group(1)
		x1 = int(m.group(2))
		y1 = int(m.group(3))
		player2 = m.group(4)
		pass
	m = gameover.match(line)
	if m:
		winner = m.group(1)
		if winner == "opponent":
			winner = 2
		else:
			winner = 1

def network():
	global net

	print "network!"

	message = net.getstring()

	networkprocess(message)

def handle_server(fd):
	global net

	ggzmod.setState(ggzmod.STATE_PLAYING)

	net.gamefd = fd
	net.init(net.gamefd)

def handle_network():
	global net

	ret = ggzmod.autonetwork()
	if ret:
		network()

def main(ggzmode):
	global net
	#global surface

	global madeturn
	global humanerror
	global message
	global winner
	global xadrez
	global aierror

	xadrez = Xadrez()

	""" Pygame setup """

	pygame.init()
	pygame.display.set_caption("Xadrez Chines/SDL")

	screen = pygame.display.set_mode((800, 600), DOUBLEBUF)

	pygame.mouse.set_visible(0)

	surface = pygame.Surface((800, 600))

	""" Game board background """

	for i in range(0, 300):
		x = sin(i / 15.0) * 20
		surface.fill((0, abs(i - 150), 150 - abs(150 - i)), ((10, i * 2), (560 + x, 1)))

	""" Menu """

	for i in range(0, 600):
		x = sin(i / 30.0) * 20
		surface.fill((65, 140, 100), ((560 + x + 10, i), (2, 1)))
		surface.fill((95, 160, 100), ((560 + x + 12, i), (2, 1)))
		surface.fill((125, 180, 100), ((560 + x + 14, i), (2, 1)))
		surface.fill((155, 200, 100), ((560 + x + 16, i), (799 - (560 + x + 16) - 10, 1)))

		surface.fill((65, 140, 100), ((0, i), (10, 1)))
		surface.fill((65, 140, 100), ((788, i), (10, 1)))

	""" Menu captions """

	font = pygame.font.Font(None, 44)
	xadrezfont = font.render("XADREZ", 1, (165, 140, 0))
	chinesfont = font.render(unic("CHINÊS"), 1, (165, 140, 0))
	sdlfont = font.render("SDL", 1, (165, 140, 0))
	font2 = pygame.font.Font(None, 70)
	slashfont = font2.render("/", 1, (165, 140, 0))

	surface.blit(xadrezfont, (580, 90))
	surface.blit(chinesfont, (580, 120))
	surface.blit(sdlfont, (710, 150))
	surface.blit(slashfont, (700, 125))

	#playernames(surface, username(), "opponent")

	""" Game stones """

	theme = "dark"

	img = {}
	img['pawn:white'] = pygame.image.load(DATAPATH + "themes/" + theme + "/pawn.png")
	img['bodyguard:white'] = pygame.image.load(DATAPATH + "themes/" + theme + "/bodyguard.png")
	img['bishop:white'] = pygame.image.load(DATAPATH + "themes/" + theme + "/bishop.png")
	img['knight:white'] = pygame.image.load(DATAPATH + "themes/" + theme + "/knight.png")
	img['cannon:white'] = pygame.image.load(DATAPATH + "themes/" + theme + "/cannon.png")
	img['rock:white'] = pygame.image.load(DATAPATH + "themes/" + theme + "/rock.png")
	img['king:white'] = pygame.image.load(DATAPATH + "themes/" + theme + "/king.png")

	alphapix = img['pawn:white']

	for pix in img.keys():
		(name, white) = pix.split(":")

		img[name + ':' + 'black'] = pygame.Surface((32, 32), 0, alphapix)
		for j in range(0, 32):
			for i in range(0, 32):
				(red, green, blue, alpha) = img[name + ':' + 'white'].get_at((i, j))
				if alpha:
					red = 255 - red
					green = 255 - green
					blue = 255 - blue
					img[name + ':' + 'black'].set_at((i, j), (red, green, blue, alpha))

	""" Points on the game board """

	stone = pygame.Surface((16, 16), 0, alphapix)
	for j in range(0, 16):
		x = sin(j / 5.0) * 8
		stone.fill((255, 255, 255, 30), ((8 - x, j), (2 * x, 1)))

	startstone = pygame.Surface((24, 24), 0, alphapix)
	for j in range(0, 24):
		x = sin(j / 7.5) * 12
		startstone.fill((255, 255, 255, 30), ((12 - x, j), (2 * x, 1)))

	blob = pygame.Surface((32, 32), 0, alphapix)
	for j in range(0, 32):
		x = sin(j / 10.0) * 16
		blob.fill((255, 255, 255, 30), ((16 - x, j), (2 * x, 1)))
	blob.fill((255, 255, 255, 100), ((14, 14), (2, 2)))

	for j in range(0, 11):
		if j is not 5:
			for i in range(0, 9):
				surface.blit(stone, (i * 55 + 40, j * 55 + 20))

	for j in (0, 10):
		for i in range(0, 9):
			surface.blit(startstone, (i * 55 + 40 - 4, j * 55 + 20 - 4))

	for j in (3, 7):
		for i in range(0, 5):
			surface.blit(startstone, (i * 2 * 55 + 40 - 4, j * 55 + 20 - 4))

	for j in (2, 8):
		for i in range(0, 2):
			surface.blit(startstone, (i * 6 * 55 + 55 + 40 - 4, j * 55 + 20 - 4))

	""" Frame around points """

	vline = pygame.Surface((8, 215))
	vline.fill((255, 255, 255))
	vline.set_alpha(15, RLEACCEL)

	hline = pygame.Surface((445, 8))
	hline.fill((255, 255, 255))
	hline.set_alpha(15, RLEACCEL)

	shline = pygame.Surface((125, 8))
	shline.fill((255, 255, 255))
	shline.set_alpha(15, RLEACCEL)

	svline = pygame.Surface((8, 115))
	svline.fill((255, 255, 255))
	svline.set_alpha(15, RLEACCEL)

	surface.blit(vline, (43, 28))
	surface.blit(vline, (483, 28))

	surface.blit(vline, (43, 360))
	surface.blit(vline, (483, 360))

	surface.blit(hline, (40, 25))
	surface.blit(hline, (40, 573))

	surface.blit(hline, (40, 245))
	surface.blit(hline, (40, 355))

	surface.blit(shline, (205, 135))
	surface.blit(shline, (205, 465))
	surface.blit(shline, (205, 80))
	surface.blit(shline, (205, 520))

	surface.blit(svline, (206, 28))
	surface.blit(svline, (261, 28))
	surface.blit(svline, (316, 28))
	surface.blit(svline, (206, 467))
	surface.blit(svline, (261, 467))
	surface.blit(svline, (316, 467))

	""" Network setup """

	madeturn = 0
	initialization = 0
	ggzsuccess = 0

	if ggzmode:
		ggzmod.setHandler(ggzmod.EVENT_SERVER, handle_server)

		ggzsuccess = ggzmod.connect()
		if ggzsuccess:
			net = Network()

	if ggzmode:
		ggzfont = pygame.font.Font(None, 20)
		if ggzsuccess:
			ggz = ggzfont.render("Running on GGZ", 1, (165, 140, 0))
			surface.blit(ggz, (580, 160))
			hint = ggzfont.render("Press 'p' for player table", 1, (165, 140, 0))
			surface.blit(hint, (580, 180))
			madeturn = 1
			initialization = 1
		else:
			ggz = ggzfont.render("GGZ unavailable", 1, (165, 140, 0))
			surface.blit(ggz, (580, 160))

	""" Main loop """

	againturn = 0
	aierror = 0
	humanerror = 0
	gameover = 0
	winner = 0
	if madeturn == 0:
		message = "It's your turn"
	else:
		message = "Initialization..."

	mouse = blob
	pressed = 0

	lastpos = (-1, -1)

	pygame.event.clear()

	while 1:
		if ggzsuccess:
			handle_network()
		pygame.event.pump()

		keyinput = pygame.key.get_pressed()

		if keyinput[K_ESCAPE] or pygame.event.peek(QUIT):
			break
		if keyinput[K_n]:
			sdlnewstuff.gethotnewstuff("xadrez-chines")
		if keyinput[K_p]:
			playertable.show()
		if keyinput[K_f]:
			pygame.display.toggle_fullscreen()

		(b1, b2, b3) = pygame.mouse.get_pressed()
		if b1 and not pressed and not madeturn:
			(x, y) = pygame.mouse.get_pos()
			x = (x - 40 + 16) / 55
			y = (y - 20 + 16) / 55
			if y > 5:
				y = y - 1
			if x >= 0 and x < 9 and y >= 0 and y < 11:
				(figure, color, options) = xadrez.components(xadrez.field[x][y])
				print "got", figure, "of color", color
				(oldx, oldy) = lastpos
				print "lastpos:", oldx, oldy
				if oldx >= 0 and oldy >= 0:
					if ggzsuccess == 1:
						frompos = str(oldx) + "," + str(oldy)
						topos = str(x) + "," + str(y)
						net.sendstring("move from " + frompos + " to " + topos)
						message = "Sending move..."
					else:
						val = xadrez.validate(oldx, oldy, x, y)
						if val is not xadrez.proto.move_invalid:
							madeturn = 1
							humanerror = 0
							message = ""
						else:
							humanerror = 1
					lastpos = (-1, -1)
				else:
					if figure is not "" and color != xadrez.aicolor():
						message = "Where to move to?"
						lastpos = (x, y)
						humanerror = 0
			pressed = 1

		if not b1 and pressed:
			pressed = 0

		screen.blit(surface, (0, 0))

		river = 0
		for y in range(0, 11):
			if y == 5:
				river = 1
			for x in range(0, 9):
				if xadrez.field[x][y] is not "":
					index = xadrez.field[x][y]
					if index.count(":") == 2:
						tmp = index.split(":")
						index = tmp[0] + ":" + tmp[1]
					screen.blit(img[index], (x * 55 + 40 - 8, (y + river) * 55 + 20 - 8))

		(x, y) = pygame.mouse.get_pos()
		screen.blit(mouse, (x - 16, y - 16))

		if xadrez.winner() != "":
			message = ""
			if xadrez.winner() == xadrez.aicolor():
				winner = 1
			else:
				winner = 2

		if winner:
			font4 = pygame.font.Font(None, 24)
			if winner == 2:
				waiting = font4.render("Game over, you lost", 1, (165, 140, 0))
			else:
				waiting = font4.render("Game over, you won", 1, (165, 140, 0))
			screen.blit(waiting, (770 - waiting.get_width(), 400))
			gameover = 1
			madeturn = 1

		if madeturn and not gameover and not initialization:
			font4 = pygame.font.Font(None, 24)
			if aierror:
				waiting = font4.render("AI error, game over", 1, (165, 140, 0))
			else:
				waiting = font4.render("Waiting for opponent", 1, (165, 140, 0))
			screen.blit(waiting, (770 - waiting.get_width(), 400))
		elif madeturn == 0:
			initialization = 0

		if humanerror:
			font4 = pygame.font.Font(None, 24)
			waiting = font4.render("Not allowed, try again", 1, (165, 140, 0))
			screen.blit(waiting, (770 - waiting.get_width(), 400))

		elif message:
			font4 = pygame.font.Font(None, 24)
			waiting = font4.render(message, 1, (165, 140, 0))
			screen.blit(waiting, (770 - waiting.get_width(), 400))

		pygame.display.flip()

		if madeturn and not aierror and not gameover and not ggzsuccess:
			ret = xadrez.ai()
			if ret == xadrez.proto.move_ok:
				madeturn = 0
				message = "It's your turn"
			else:
				aierror = 1

if __name__ == "__main__":
	if len(sys.argv) == 2 and sys.argv[1] == "--ggz":
		main(1)
	else:
		main(0)

