import pygame, sys,os ,pickle
from pygame.locals import *
from random import *
from pickle import *

pygame.init()
if not pygame.font: 	print 'Warning, fonts disabled'
if not pygame.mixer: 	print 'Warning, sound disabled'

window = pygame.display.set_mode((160,160))
screen = pygame.Surface((160,160)).convert()
font = pygame.font.Font(None,20)
clock = pygame.time.Clock()
pygame.mouse.set_visible(1)
pygame.display.set_caption("nu")

########################################################################
#######################base function####################################
########################################################################


########################################################################
#######################image building###################################
########################################################################

image_score = []
for combo in  range(21) :
	image = font.render(str(combo),0,(255,128,128),(255,255,255)).convert()
	image.set_colorkey(image.get_at((0,0)), RLEACCEL)
	image_score.append(image)

def load_file(numb):
	name = str(numb) + ".dct"
	try:
		fichier = open((os.path.join('data', name)), 'rwb')
	except IOError, (errno, strerror):
		fichier = open((os.path.join('data', name)), 'wb')
		pickle.dump({},fichier)
		fichier = open((os.path.join('data', name)), 'rwb')
	return fichier

try:   	background = pygame.image.load((os.path.join('data', 'clickeux.png'))).convert()
except pygame.error, message:
	background = pygame.Surface((160,160)).convert()
	background.fill((255,255,255))

try:	single_scale = pygame.image.load((os.path.join('data', 'single_scale.png'))).convert()
except pygame.error, message:
	single_scale = font.render("1x",0,(0,0,0),(255,255,255)).convert()
single_scale.set_colorkey(single_scale.get_at((0,0)), RLEACCEL)

try:	double_scale = pygame.image.load((os.path.join('data', 'double_scale.png'))).convert()
except pygame.error, message:
	double_scale = font.render("2x",0,(0,0,0),(255,255,255)).convert()
double_scale.set_colorkey(double_scale.get_at((0,0)), RLEACCEL)

try:	quad_scale = pygame.image.load((os.path.join('data', 'quad_scale.png'))).convert()
except pygame.error, message:
	quad_scale = font.render("4x",0,(0,0,0),(255,255,255)).convert()
quad_scale.set_colorkey(quad_scale.get_at((0,0)), RLEACCEL)

try:	up_arrow = pygame.image.load((os.path.join('data', 'up_arrow.png'))).convert()
except pygame.error, message:
	up_arrow = pygame.Surface((5,5)).convert()
	pygame.draw.polygon(up_arrow, (255,255,0), [(2,0),(4,5),(0,4)])
up_arrow.set_colorkey(up_arrow.get_at((0,0)), RLEACCEL)

try:	down_arrow = pygame.image.load((os.path.join('data', 'down_arrow.png'))).convert()
except pygame.error, message:
	down_arrow = pygame.Surface((5,5)).convert()
	pygame.draw.polygon(down_arrow, (255,255,0), [(2,4),(4,0),(0,0)])
down_arrow.set_colorkey(down_arrow.get_at((0,4)), RLEACCEL)

try:	button_build = pygame.image.load((os.path.join('data', 'button_build.png'))).convert()
except pygame.error, message:
	button_build = font.render("go",0,(0,0,0),(255,255,255)).convert()
button_build.set_colorkey(button_build.get_at((0,4)), RLEACCEL)

try:	blok_square = pygame.image.load((os.path.join('data', 'blok_square.png'))).convert()
except pygame.error, message:
	blok_square = pygame.Surface((10,10)).convert()
	blok_square.fill((0,255,0))
	pygame.draw.rect(blok_square,(255,255,255),pygame.Rect(2,2,6,6),0)
	blok_square.set_colorkey((255,255,255), RLEACCEL)

try:	blok_lift = pygame.image.load((os.path.join('data', 'blok_lift.png'))).convert()
except pygame.error, message:
	blok_lift = pygame.Surface((10,160)).convert()
	blok_lift.fill((0,255,0))
	pygame.draw.rect(blok_lift,(255,255,255),pygame.Rect(2,0,6,160),0)
	blok_lift.set_colorkey((255,255,255), RLEACCEL)

def blok_build(color):
	image = pygame.Surface((10,10)).convert()
	pygame.draw.rect(image,color,pygame.Rect(1,1,8,8),0)
	image.set_colorkey((255,255,255), RLEACCEL)
	return image

def blik_build(color):
	image = pygame.Surface((6,1)).convert()
	image.fill(color)
	return image

################################################################################################
##################################mouse sprite##################################################
################################################################################################

class spr_mice(pygame.sprite.Sprite):
	def __init__(self):
		pygame.sprite.Sprite.__init__(self)
		self.rect = pygame.Rect(0,0,0,0)
		self.screen_do = None
		self.mouse_do = None

	def update(self):
		(self.rect.x, self.rect.y) = pygame.mouse.get_pos()

spr_mice = spr_mice()

##################################################################################################
###################################THOSE BLOK#####################################################
##################################################################################################

grp_blok = pygame.sprite.RenderUpdates()

matrix_blok = []
for x in range(10):
	matrix_blok.append([])
	for y in range(16):
		matrix_blok[x].append(None)

class spr_blok(pygame.sprite.Sprite):
	def __init__(self, xpos, ypos, image, group, target):
		pygame.sprite.Sprite.__init__(self)
		self.image = image
		self.rect = self.image.get_rect().move(xpos,ypos)
		self.group = group
		self.do = self.collapse
		self.target = target
		self.combo = 0
		self.matrix = matrix_blok
		self.matrix[self.rect.x/10][self.rect.y/10] = self

	def update(self):
		self.do()

	def go_left(self):
		pass

	def go_right(self):
		pass

	def collapse(self):
		self.oldy = self.rect.y
		self.matrix[self.rect.x/10][self.rect.y/10] = None
		self.rect.move_ip(0,5)
		if self.rect.bottom > 160:
			self.rect.y = self.oldy
		if (self.matrix[self.rect.x/10][(self.rect.y+5)/10] != None) :
			self.rect.y = self.oldy
		self.matrix[self.rect.x/10][self.rect.y/10] = self

		if self.rect.bottom >= 159:
			if self.rect.left > 10:
				if (self.matrix[(self.rect.x-10)/10][(self.rect.y)/10] == None) :
					self.do = self.go_left
			if self.rect.right < 90:
				if (self.matrix[(self.rect.x+10)/10][(self.rect.y)/10] == None) :
					self.do = self.go_right


	def clicked(self):
		if self.rect.left > 0:
			self.left = self.matrix[(self.rect.x-10)/10][self.rect.y/10]
		else :	self.left = None
		if self.rect.right < 100:
			self.right = self.matrix[(self.rect.x+10)/10][self.rect.y/10]
		else :	self.right = None
		if self.rect.top > 0:
			self.top = self.matrix[self.rect.x/10][(self.rect.y-10)/10]
		else :	self.top = None
		if self.rect.bottom < 160:
			self.bottom = self.matrix[self.rect.x/10][(self.rect.y+10)/10]
		else :	self.bottom = None

		around = [(self.left),(self.right),(self.top),(self.bottom)]
		for side in around:
			if side != None:
				if side.image == self.image:
					side.do = side.clicked
					side.combo += 1
					self.combo += 1
					self.combo = side.combo = side.combo + self.combo

		if self.combo > 20 :
			self.combo = 20
		self.image = image_score[self.combo]

		self.matrix[self.rect.x/10][self.rect.y/10] = None
		self.remove(self.group)
		self.add(self.target)

		self.do = self.score

	def score(self):
		if (self.rect.x, self.rect.y) != (120,20) :
			self.rect.y += 5 * (20 - self.rect.y) / (120 - self.rect.x)
			self.rect.x += 5

###############################################################################################
#############################scaler sprite#####################################################
###############################################################################################

class spr_single(pygame.sprite.Sprite):
	def __init__(self,xpos,ypos, mouse):
		pygame.sprite.Sprite.__init__(self)
		self.image = single_scale
		self.rect = self.image.get_rect().move(xpos,ypos)
		self.mouse = mouse

	def scale_screen(self,screen,window):
		window.blit(screen,(0,0))

	def scale_mouse(self,mouse):
		pass

	def click(self):
		window = pygame.display.set_mode((160,160))
		self.mouse.mouse_do = self.scale_mouse
		self.mouse.screen_do = self.scale_screen

class spr_double(pygame.sprite.Sprite):
	def __init__(self,xpos,ypos, mouse):
		pygame.sprite.Sprite.__init__(self)
		self.image = double_scale
		self.rect = self.image.get_rect().move(xpos,ypos)
		self.mouse = mouse

	def scale_screen(self,screen,window):
		scaled = pygame.transform.scale2x(screen)
		window.blit(scaled,(0,0))

	def scale_mouse(self,mouse):
		mouse.rect.x, mouse.rect.y = mouse.rect.x/2, mouse.rect.y/2

	def click(self):
		window = pygame.display.set_mode((320,320))
		self.mouse.mouse_do = self.scale_mouse
		self.mouse.screen_do = self.scale_screen

class spr_quad(pygame.sprite.Sprite):
	def __init__(self,xpos,ypos, mouse):
		pygame.sprite.Sprite.__init__(self)
		self.image = quad_scale
		self.rect = self.image.get_rect().move(xpos,ypos)
		self.mouse = mouse

	def scale_screen(self,screen,window):
		scaled = pygame.transform.scale2x(screen)
		scaled = pygame.transform.scale2x(scaled)
		window.blit(scaled,(0,0))

	def scale_mouse(self,mouse):
		mouse.rect.x, mouse.rect.y = mouse.rect.x/4, mouse.rect.y/4

	def click(self):
		window = pygame.display.set_mode((640,640))
		self.mouse.mouse_do = self.scale_mouse
		self.mouse.screen_do = self.scale_screen


spr_single = spr_single(111,0, spr_mice)
spr_double = spr_double(128,0, spr_mice)
spr_quad = spr_quad(145,0, spr_mice)
grp_button = pygame.sprite.RenderUpdates((spr_single, spr_double, spr_quad))

#############################################################################################
################################SCORE SPRITE#################################################
#############################################################################################

grp_combo = pygame.sprite.RenderUpdates()

class spr_combo(pygame.sprite.Sprite):
	def __init__(self,xpos,ypos,group):
		pygame.sprite.Sprite.__init__(self)
		self.score = self.old = 0
		self.group = group
		self.image = font.render(str(0),0,(255,128,128),(255,255,255)).convert()
		self.image.set_colorkey(self.image.get_at((0,0)), RLEACCEL)
		self.rect = self.image.get_rect().move(xpos,ypos)
		self.xpos, self.ypos = xpos, ypos

	def update(self):
		if self.score != self.old :
			self.image = font.render(str(self.score),0,(255,128,128),(255,255,255)).convert()
			self.rect = self.image.get_rect().move(self.xpos,self.ypos)
			self.image.set_colorkey(self.image.get_at((0,0)), RLEACCEL)
		self.old = self.score
		for sprite in pygame.sprite.spritecollide(self, self.group, False) :
			self.score += sprite.combo
			sprite.kill()

	def click(self):
		pass

spr_combo = spr_combo(111,20,grp_combo)
grp_button.add(spr_combo)

class high_score(pygame.sprite.Sprite):
	def __init__(self):
		pygame.sprite.Sprite.__init__(self)
		hall_of_fame = {}

	def update(self):
		pass

	def draw(self):
		pass

high_score = high_score()

##################################################################################################
###################################level choice###################################################
##################################################################################################

def lvl_build(lvl_numb):
	new_grp_blok = pygame.sprite.RenderUpdates()
	#try to load a png that contain a level to build
	try:
		name = os.path.join('data', str(lvl_numb) + ".png")
		lvl_image = pygame.image.load((name)).convert()
		image_dict = {}
		color_list = []
		for x in range(0,10,1) :
			for y in range(0,16,1):
				color = lvl_image.get_at((x,y))
				if color not in image_dict :
					image_dict[color] = blok_build(color)
				blok_image = image_dict[color]
				grp_blok.add(spr_blok(x*10,y*10,blok_image,grp_blok, grp_combo))
	#random if no image available
    	except pygame.error, message:
		image_all = [blok_build((0,0,255)), blok_build((255,0,0)), blok_build((0,255,0))]
		for x in range(0,100,10) :	
			for y in range(10,160,10) :
				grp_blok.add(spr_blok(x,y,choice(image_all),grp_blok, grp_combo))
	return new_grp_blok

class spr_lvl_num(pygame.sprite.Sprite):
	def __init__(self, xpos, ypos):
		pygame.sprite.Sprite.__init__(self)
		self.level = self.old = 0
		self.image = font.render(str(self.level),0,(255,128,128),(255,255,255)).convert()
		self.rect = self.image.get_rect().move(xpos,ypos)
		self.image.set_colorkey(self.image.get_at((0,0)), RLEACCEL)
		self.xpos, self.ypos = xpos, ypos

	def update(self):
		if self.level < 0:
			self.level = 0
		if self.old != self.level :
			self.image = font.render(str(self.level),0,(255,128,128),(255,255,255)).convert()
			self.rect = self.image.get_rect().move(self.xpos,self.ypos)
			self.image.set_colorkey(self.image.get_at((0,0)), RLEACCEL)
		self.old = self.level

	def click(self):
		pass

	def load(self):
		pass

class spr_lvl_inc(pygame.sprite.Sprite):
	def __init__(self, xpos, ypos,cntr):
		pygame.sprite.Sprite.__init__(self)
		self.level = 1
		self.image = up_arrow
		self.rect = self.image.get_rect().move(xpos,ypos)
		self.cntr = cntr

	def click(self):
		self.cntr.level += 1

class spr_lvl_dec(pygame.sprite.Sprite):
	def __init__(self, xpos, ypos,cntr):
		pygame.sprite.Sprite.__init__(self)
		self.level = -1
		self.image = down_arrow
		self.rect = self.image.get_rect().move(xpos,ypos)
		self.cntr = cntr

	def click(self):
		self.cntr.level -= 1
		if self.cntr.level < 0:
			self.cntr.level = 0

class spr_lvl_build(pygame.sprite.Sprite):
	def __init__(self, xpos, ypos,now_score, hi_score,all_sprite, lvl_cntr ):
		pygame.sprite.Sprite.__init__(self)
		self.image = button_build
		self.rect = self.image.get_rect().move(xpos,ypos)

		self.now_score = now_score
		self.hi_score = hi_score
		self.lvl_cntr = lvl_cntr
		self.all_sprite = all_sprite

	def make(self,grp_blok,level_numb):
		grp_blok.empty()
		grp_blok = lvl_build(level_numb)



	def click(self):
		self.make(self.all_sprite, self.lvl_cntr.level)
		self.now_score.score = 0

spr_lvl_num = spr_lvl_num(130,140)
spr_lvl_build = spr_lvl_build(111,140,spr_combo, high_score, grp_blok, spr_lvl_num)
spr_lvl_inc = spr_lvl_inc(152,139,spr_lvl_num)
spr_lvl_dec = spr_lvl_dec(152,148,spr_lvl_num)
grp_button.add((spr_lvl_num, spr_lvl_inc, spr_lvl_dec, spr_lvl_build))

###############################################################################################
##################################the main loop################################################
###############################################################################################

spr_single.click()
spr_lvl_build.click()

while True :
	clock.tick(24)
	for event in pygame.event.get():
		if event.type == QUIT:
			sys.exit(0)
    		elif event.type == MOUSEBUTTONDOWN:
			#those blok
			for sprite_click in pygame.sprite.spritecollide (spr_mice, grp_blok, False) :
				sprite_click.do = sprite_click.clicked	
			#compare button with mouse
			for sprite_click in pygame.sprite.spritecollide (spr_mice, grp_button, False) :
				sprite_click.click()

#those blok
	grp_blok.update()
	grp_blok.draw(screen)

#all button like scaler , score , level chooser
	grp_button.update()
	grp_button.draw(screen)
#blok that becom combo and will be drawn on top of the rest
	grp_combo.update()
	grp_combo.draw(screen)
#screen update
	spr_mice.update()
	spr_mice.mouse_do(spr_mice)
	spr_mice.screen_do(screen,window)
	pygame.display.flip()
	screen.blit(background,(0,0))
