import pyxel, random
from pieces import *

pyxel.init(15*8, 20*8, title='TETRIS', fps = 60)
pyxel.load('res.pyxres')

board = []
colors = {}
grace = True
frame = -1
level = 0
score = 0
soft = 0
total = 0

def check(x, y, rotation, block):
    if any(i[0]+x > 9 or i[0]+x < 0 or i[1]+y == 20 or [i[0]+x, i[1]+y] in board for i in PIECES[block][rotation]):
        return True
    else:
        return False

def move(x):
    if ((pyxel.btn(pyxel.KEY_LEFT) and pyxel.frame_count % 6 == 0) or pyxel.btnp(pyxel.KEY_LEFT)) and not check(x-1, piece.y, piece.rotation, piece.block):
        x -= 1
    elif ((pyxel.btn(pyxel.KEY_RIGHT) and pyxel.frame_count % 6 == 0) or pyxel.btnp(pyxel.KEY_RIGHT)) and not check(x+1, piece.y, piece.rotation, piece.block):
        x += 1
    return x

def rotate(rotation):
    if (pyxel.btnp(pyxel.KEY_Z) or pyxel.btnp(pyxel.KEY_UP)) and not check(piece.x, piece.y, (rotation-1)%len(PIECES[piece.block]), piece.block):
        rotation = (rotation-1)%len(PIECES[piece.block])
    elif pyxel.btnp(pyxel.KEY_X) and not check(piece.x, piece.y, (rotation+1)%len(PIECES[piece.block]), piece.block):
        rotation = (rotation+1)%len(PIECES[piece.block])
    return rotation


def fall(y, soft):
    global score
    hard_score = 0
    ground = check(piece.x, y+1, piece.rotation, piece.block)
    if pyxel.btnp(pyxel.KEY_SPACE):
        while check(piece.x, y+1, piece.rotation, piece.block) == False:
            y += 1
            hard_score += 2
        ground = True
        score += hard_score
    elif not ground:
        y += 1
        if pyxel.btn(pyxel.KEY_DOWN):
            soft += 1
    return y, ground, soft

def line_clear():
    y_board = list(set([i[1] for i in board]))
    y_board.sort()
    lines = 0
    new_board = []
    for i in y_board:
        current_board = new_board.copy() if new_board != [] else board.copy()
        if [h[1] for h in current_board].count(i) == 10:
            new_board = []
            for j in range(len(current_board)):
                if current_board[j][1] < i:
                    new_board.append([current_board[j][0], current_board[j][1]+1])
                    colors[(current_board[j][0], current_board[j][1]+1)] = colors[(current_board[j][0], current_board[j][1])]
                    del colors[(current_board[j][0], current_board[j][1])]
                elif current_board[j][1] > i:
                    new_board.append(board[j])
            lines += 1
            y_board = [i+1 for i in y_board]
            # print(board)
            # print("line ", 19-i, "cleared")
            # print(new_board)
    return new_board if lines != 0 else board, lines


class tetromino:
    def __init__(self):
        self.block = random.choice(list(PIECES))
        # self.block = "T"
        self.rotation = 0
        self.x = 5
        self.y = 0
        self.color = PIECE_COLOR[self.block]

def create_piece():
    instance = tetromino()
    return instance

piece = create_piece()
next_piece = create_piece()

def update():
    global board, piece, next_piece, grace, colors, score, soft, level, total
    board, lines = line_clear()
    total += lines
    level = total // 10
    g = LEVEL_SPEED[level]
    if pyxel.btn(pyxel.KEY_DOWN):
        g = 2
    match lines:
        case 1:
            score += 40*(level+1)
        case 2:
            score += 100*(level+1)
        case 3:
            score += 300*(level+1)
        case 4:
            score += 1200*(level+1)
    piece.x = move(piece.x)
    piece.rotation = rotate(piece.rotation)
    if pyxel.frame_count % g == 0 or pyxel.btnp(pyxel.KEY_SPACE):
        piece.y, collision, soft = fall(piece.y, soft)
        # collision = False
        if collision == True:
            if grace == False or pyxel.btnp(pyxel.KEY_SPACE):
                if not pyxel.btnp(pyxel.KEY_SPACE):
                    score += soft
                    soft = 0
                for i in PIECES[piece.block][piece.rotation]:
                    board.append([i[0]+piece.x, i[1]+piece.y])
                    colors[(i[0]+piece.x, i[1]+piece.y)] = piece.color
                    board.sort(key=lambda x: (x[1], x[0]), reverse=True)
                # print(board)
                grace = True
                piece = next_piece
                next_piece = create_piece()
            else:
                grace = False


def draw():
    pyxel.cls(0)
    pyxel.rect(10*8, 0, 5*8, 20*8, 1)
    x, y = piece.x, piece.y
    for i in PIECES[next_piece.block][next_piece.rotation]:
        pyxel.rect((i[0]+11.5)*8 if next_piece.block in ["I", "O"] else (i[0]+12)*8, (i[1]+2)*8, 8, 8, next_piece.color)
    for i in PIECES[piece.block][piece.rotation]:
        pyxel.rect((i[0]+x)*8, (i[1]+y)*8, 8, 8, piece.color)
        # pyxel.blt((i[0]+x)*8, (i[1]+y)*8, 0, 8 if i == [0, 0] else 0, 0, 8, 8)
    for i in board:
        pyxel.rect((i[0])*8, (i[1])*8, 8, 8, colors[tuple(i)])
        # pyxel.blt((i[0])*8, (i[1])*8, 0, 0, 8, 8, 8)
    pyxel.text(11*8, 5*8, "0"*(6-len(str(score)))+str(score), pyxel.COLOR_WHITE)
    pyxel.text(11*8, 6*8, "LEVEL "+str(level), pyxel.COLOR_WHITE)

pyxel.run(update, draw)