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)

try:       background = pygame.image.load((os.path.join('data', 'clickeux.png'))).convert()
except pygame.error:
    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:
    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:
    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:
    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:
    dead = font.render("X",0,(255,0,0),(255,255,255)).convert()
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:
    image_new_game = font.render("new_game",0,(255,0,0),(255,255,255)).convert()
image_new_game.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

################################################################################################
##################################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(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 gameover(self):
        for sprite in self.group:
            sprite.do = sprite.die

    def die(self):
        self.image = dead
        
    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
        elif self.ypos <= 0:
            self.do = self.die

    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 < 15:
            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
        elif self.ypos == 15:
            pass    #go left
        self.xdest, self.ydest =  self.xpos*10, self.ypos*10

    def clicked(self):
        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 < 15 :
            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

        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.xpos][self.ypos] = 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()

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

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

class spr_new_game(pygame.sprite.Sprite):
    def __init__(self,xpos,ypos,image,group,image_list):
        pygame.sprite.Sprite.__init__(self)
        self.image = image
        self.rect = self.image.get_rect().move(xpos,ypos)
        self.group = group
        self.lst = image_list
        self.alive = True

    def click(self):
        self.group.empty()
        self.lst = [blok_build((0,0,255)), blok_build((255,0,0)), blok_build((0,255,0))]


spr_new_game = spr_new_game(110,140,image_new_game,grp_blok,image_all)
grp_button.add(spr_new_game)




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

alive = True
old = pygame.time.get_ticks()
spr_double.click()


while True :
    clock.tick(24)
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit(0)
        else:
            if event.type == MOUSEBUTTONDOWN:
                #those blok
                if 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 alive == True:
        new = pygame.time.get_ticks()
        if new >= old + 4000 :
            old = new
            for x in range(0,100,10) :
                if matrix_blok[x/10][16] == None:
                    new_blok = spr_blok(x,160,choice(image_all),grp_blok, grp_combo)
                    new_blok.do = new_blok.jump
                    grp_blok.add(new_blok)
        for x in range(0,100,10) :            
            if matrix_blok[x/10][0] != None:
                alive = False
                matrix_blok[x/10][0].do = matrix_blok[x/10][0].gameover

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