import pyxel

#https://adventofcode.com/2022/day/14

PATH_INPUT = 'input1.py'

AIR = 0
ROCHE = 1
SABLE = 2
PASSE = 3

       
        
class Puzzle:
    
    def __init__(self, path):
        self.path = path
        self.roche = []
        self.colmin = float('inf')
        self.colmax = -float('inf')
        self.ligmin = float('inf')
        self.ligmax = -float('inf')
        self.grid = self.parse()
        self.iteration = -1
        pyxel.init(len(self.grid[0]), len(self.grid),fps=120)
        pyxel.run(self.update, self.draw)
        
        
    def parse(self):
        f = open(self.path)
        self.roche = []
        for ligne in f:
            self.roche.append([self.conversion(champ) for champ in ligne.rstrip().split(' -> ')])
        f.close()
        self.colmax = max(self.colmax, 500 + self.ligmax + 2)
        self.colmin = min(self.colmin,  500 - self.ligmax - 2)
        self.grid = [[AIR for _ in range(self.colmax - self.colmin + 1)] for __ in range(self.ligmax + 3)]
        for scan in self.roche:
            colp, ligp = scan[0]
            for point in scan[1:]:
                col, lig = point
                if ligp == lig:
                    dc = (col - colp) // (max(colp, col) - min(colp, col))
                    k = colp
                    while k != col:
                        self.grid[lig][k - self.colmin] = ROCHE
                        k += dc
                    self.grid[lig][k - self.colmin] = ROCHE
                else:
                    dl = (lig - ligp) // (max(ligp, lig) - min(ligp, lig))
                    k = ligp
                    while k != lig:
                        self.grid[k][colp - self.colmin] =  ROCHE
                        k += dl
                    self.grid[k][colp - self.colmin] = ROCHE
                colp, ligp = col, lig
        for col in range(self.colmax - self.colmin + 1):
            self.grid[self.ligmax + 2][col] = ROCHE
        return  self.grid

    
    def conversion(self, champ):
        col, lig = champ.split(',')
        lig = int(lig)
        col = int(col)
        if col < self.colmin:
            self.colmin = col
        if col > self.colmax:
            self.colmax = col
        if lig < self.ligmin:
            self.ligmin = lig
        if lig > self.ligmax:
            self.ligmax = lig
        return [col, lig]
    
    def get_grid(self):
        return repr(self.grid)
    
    def percolate(self, lig, col, iteration): 
        self.grid[lig][col] = iteration
        if lig + 1 <= self.ligmax + 2 and self.grid[lig + 1][col]  <= AIR:
            self.percolate(lig + 1, col, iteration)
            return
        if lig + 1 <= self.ligmax + 2  and col - 1 >= 0 and self.grid[lig + 1][col - 1] <= AIR:
            self.percolate(lig + 1, col - 1, iteration)
            return
        if lig + 1 <= self.ligmax + 2  and col + 1 < self.colmax - self.colmin  and self.grid[lig + 1][col + 1]  <= AIR:
            self.percolate(lig + 1, col + 1, iteration)
            return
        self.grid[lig][col] = SABLE
        return
    
    def update(self):        
        self.iteration -= 1
        if self.grid[0][500 - self.colmin] != SABLE:            
            self.percolate(0, 500 - self.colmin, self.iteration)
            
            
    def draw(self):        
        for lig in range(len(self.grid)):
            for col in range(len(self.grid[0])):
                if self.grid[lig][col] == SABLE or self.grid[lig][col] == self.iteration:
                    pyxel.rect(col, lig, 1, 1, 10)
                elif self.grid[lig][col] == ROCHE:
                    pyxel.rect(col, lig, 1, 1, 0)
                else:
                    pyxel.rect(col, lig, 1, 1, 8)
                
    
if __name__ == "__main__":
    puzzle2 = Puzzle(PATH_INPUT)