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("ku")

########################################################################
#######################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 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

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:   	dead = pygame.image.load((os.path.join('data', 'dead.png'))).convert()
except pygame.error, message:
	dead = blok_build((140,140,140))
dead.set_colorkey((255,255,255), RLEACCEL)

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


################################################################################################
##################################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#####################################################
##################################################################################################

new_grp_blok = pygame.sprite.RenderUpdates()
grp_blok = pygame.sprite.RenderUpdates()

matrix_blok = []
for x in range(10):
	matrix_blok.append([])
	for y in range(17):
		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.xdest, self.ydest = xpos,ypos
		self.group = group
		self.do = self.collapse
		self.target = target
		self.combo = 0
		self.matrix = matrix_blok
		self.xpos, self.ypos = xpos/10, ypos/10
		self.matrix[self.xpos][self.ypos] = self

	def update(self):
		self.do()

	def jump(self):
		if self.ypos > 0 :
			if self.matrix[self.xpos][self.ypos - 1] != None:
				self.matrix[self.xpos][self.ypos - 1].do = self.matrix[self.xpos][self.ypos - 1].jump
			elif self.matrix[self.xpos][self.ypos - 1] == None:
				self.matrix[self.xpos][self.ypos] = None
				self.ypos -= 1
				self.matrix[self.xpos][self.ypos] = self
				self.do = self.collapse

	def collapse(self):
		if self.rect.x < self.xdest:	xmove = 5
		elif self.rect.x > self.xdest:	xmove = -5
		else:				xmove = 0
		if self.rect.y < self.ydest:	ymove = 5
		elif self.rect.y > self.ydest:	ymove = -5
		else:				ymove = 0
		self.rect.move_ip(xmove,ymove)
		if self.ypos < 14:
			if self.matrix[self.xpos][self.ypos + 1] == None:
				self.matrix[self.xpos][self.ypos] = None
				self.ypos += 1
				self.matrix[self.xpos][self.ypos] = self
		self.xdest, self.ydest =  self.xpos*10, self.ypos*10

	def clicked(self):
            if self.ypos < 15:
		if self.ypos > 0 :  self.top = self.matrix[self.xpos][self.ypos-1]
		else:               self.top = None
		if self.xpos > 0 :  self.left = self.matrix[self.xpos-1][self.ypos]
		else:               self.left = None
		if self.ypos < 14 : self.bottom = self.matrix[self.xpos][self.ypos+1]
		else:               self.bottom = None
		if self.xpos < 9 :  self.right = self.matrix[self.xpos+1][self.ypos]
		else:               self.right = None
  
		for side in [(self.left),(self.right),(self.top),(self.bottom)]:
        	    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
                if self.combo <= 1:     #only 3 or more should be scored
                    self.do = self.collapse
                else:
                    self.image = image_score[self.combo]
                    self.matrix[self.xpos][self.ypos] = None
                    self.remove(self.group)
                    self.add(self.target)
                    self.do = self.score
	    else:
                self.do = self.collapse

 	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

class spr_dead(pygame.sprite.Sprite):
        def __init__(self,xpos,ypos,group_blok,matrix_blok):
                pygame.sprite.Sprite.__init__(self)
		self.image = dead
		self.rect = self.image.get_rect().move(xpos*10,ypos*10)
		self.matrix = matrix_blok
		self.xpos, self.ypos = xpos, ypos
		self.matrix[self.xpos][self.ypos] = self
		self.add(group_blok)

	def update(self):
            pass

        def draw(self):
            pass

###############################################################################################
#############################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()

##################################################################################################
###################################New Game#######################################################
##################################################################################################

grp_blok.empty()
image_all = [blok_build((0,0,255)), blok_build((255,0,0)), blok_build((0,255,0))]

class new_game(pygame.sprite.Sprite):
        def __init__(self,image,xpos,ypos,grp_blok,matrix_blok,grp_button,spr_combo):
                pygame.sprite.Sprite.__init__(self)
                self.image = image
                self.rect = self.image.get_rect().move(xpos,ypos)
                self.grp_blok = grp_blok
                self.grp_button = grp_button
                self.matrix_blok = matrix_blok
                self.alive = True
                self.combo = spr_combo
                self.delay = 200
                self.level = 0
                
        def update(self):
                pass

        def draw(self):
                pass

        def click(self):
                self.remove(self.grp_button)
                self.grp_blok.empty()        #all blok should be deleted
                for x in range(0,10):           #and the entire matrix
                        for y in range(0,16):   #should be filled with
                                matrix_blok[x][y] = None
                self.alive = True
                self.combo.score = 0
                self.delay = 200
                self.level = 0

new_game = new_game(image_new_game,20,70,grp_blok,matrix_blok,grp_button,spr_combo)
            
###############################################################################################
##################################the main loop################################################
###############################################################################################

pivot = 0       #a line of blok that increase
old = pygame.time.get_ticks()   #last time we added a blok

spr_double.click()  # 2x scale setup


while True :
	clock.tick(24)
	for event in pygame.event.get():
		if event.type == QUIT:
			sys.exit(0)
    		elif event.type == MOUSEBUTTONDOWN:
			#those blok
			if new_game.alive == True:
				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)
	if new_game.alive == True:
		new = pygame.time.get_ticks()   #it is time to add a blok below
		if new >= old + new_game.delay :           #oh yes we can
			old = new               #save new timer value for next time
			if pivot >= 10:         #make sure we dont have already 10 blok below
				pivot = 0
			if matrix_blok[pivot][15] == None:  #make sure position below is not taken
				new_blok = spr_blok(pivot*10,150,choice(image_all),grp_blok, grp_combo)
				grp_blok.add(new_blok)      #create new blok at given position
				pivot += 1                  #increase pivot
                        else:
                                matrix_blok[pivot][15].do = matrix_blok[pivot][15].jump

		for x in range(0,100,10) :          #line scan
			if pivot >= 10:             #if we have 10 on 1st line
				if matrix_blok[x/10][15] != None:
					new_blok = matrix_blok[x/10][15]
					new_blok.do = new_blok.jump
			if matrix_blok[x/10][0] != None:    #if we have one on last line
				new_game.alive = False

        elif new_game.alive == False:
                grp_button.add(new_game)
                grp_blok.empty()        #all blok should be deleted
                for x in range(0,10):           #and the entire matrix
                        for y in range(0,16):   #should be filled with
                                matrix_blok[x][y] = spr_dead(x,y,grp_blok,matrix_blok)
                new_game.alive = None

        if spr_combo.score >= 4000:
            if spr_combo.score >= 8000:
                if spr_combo.score >= 16000:
                    if spr_combo.score >= 24000:
                        if spr_combo.score >= 40000:
                            new_game.delay = 100
                            new_game.level = 5
                        else:
                            new_game.delay = 120
                            new_game.level = 4
                    else:
                        new_game.delay = 140
                        new_game.level = 3
                else:
                    new_game.delay = 160
                    new_game.level = 2
            else:
                new_game.delay = 180
                new_game.level = 1
        else:
            new_game.delay = 200
            new_game.level = 0
                                

#all button like scaler , score , level chooser
	grp_button.update()             #all button
	grp_button.draw(screen)
#blok that becom combo and will be drawn on top of the rest
	grp_combo.update()              #score
	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))
