#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import numpy as np
from PIL import Image, ImageDraw, ImageFont
import cv2
from time import time

file = "./input.txt"
#file = "./ex.txt"
#file = "./ex_s.txt"
out_file_name = "sol_bigger"
grow_factor = 10

start_time = time()

def array_to_image(ar):
    global grow_factor
    # Konvertiere das Array in ein NumPy-Array
    np_array = np.array(ar)
    # Erstelle ein leeres RGB-Bild
    height, width = np_array.shape
    image = Image.new('RGB', (width * grow_factor, height * grow_factor))
    # Fülle das Bild mit Pixeln basierend auf den Array-Werten
    for y in range(height):
        for x in range(width):
            color = (0, 0, 0)  # Standardfarbe schwarz
            if np_array[y, x] == "#":
                color = (255, 0, 0)
            elif np_array[y, x] == "O":
                color = (0, 255, 0)
            elif np_array[y, x] == "@":
                color = (255, 255, 255)
            for dy in range(grow_factor):
                for dx in range(grow_factor):
                    image.putpixel((x * grow_factor + dx, y * grow_factor + dy), color)

    return image

def add_text_to_image(image, num):
    draw = ImageDraw.Draw(image)
    font = ImageFont.truetype("arial.ttf", 20)  # Wählen Sie eine Schriftart und Größe
    draw.text((5,5), f"{num:04d}", fill=(255, 255, 255), font=font)  # Weißer Text
    return image

def pil_to_cv2(pil_image):
    return cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)

def read_input(input_file:str) -> tuple[list[list[str]], list[str]]:
    out_field=[]
    out_moves=[]
    f = open(input_file, "r")
    for line in f:
        line = line.strip()
        if line == "":
            continue
        if "#" in line:
            temp = []
            for b in line:
                temp.append(b)
            out_field.append(temp)
        elif "<" in line or ">" in line or "^" in line or "v" in line:
            out_moves.append(line)
    f.close()
    return out_field, out_moves

def get_position(game_field) -> (int, int):
    for li in range(len(game_field)):
        for ro in range(len(game_field[li])):
            if game_field[li][ro] == '@':
                return li, ro

def print_field(f:list[list[str]]):
    for r in f:
        for s in r:
            print(s, end="")
        print()

def do_move(f:list[list[str]], m:str)-> list[list[str]]:
    li, ro = get_position(f)
    #print(li, ro, m)
    if m == ">":
        for i in range(ro+1, len(f[li])):
            if f[li][i] == '.':
                for ml in range(i,ro,-1):
                    f[li][ml] = f[li][ml-1]
                f[li][ro] = '.'
                return f
            elif f[li][i] == '#':
                return f
    elif m == "<":
        for i in range(ro-1, 0, -1):
            if f[li][i] == '.':
                for ml in range(i,ro):
                    f[li][ml] = f[li][ml+1]
                f[li][ro] = '.'
                return f
            elif f[li][i] == '#':
                return f
    elif m == "v":
        for i in range(li+1, len(f)):
            if f[i][ro] == '.':
                for mr in range(i,li,-1):
                    f[mr][ro] = f[mr-1][ro]
                f[li][ro] = '.'
                return f
            elif f[i][ro] == '#':
                return f
    elif m == "^":
        for i in range(li-1, 0, -1):
            if f[i][ro] == '.':
                for mr in range(i,li):
                    f[mr][ro] = f[mr+1][ro]
                f[li][ro] = '.'
                return f
            elif f[i][ro] == '#':
                return f
    return f

def sum_gps_coord(f:list[list[str]]):
    result = 0
    for l in range(len(f)):
        for r in range(len(f[l])):
            if f[l][r] == "O":
                result += (100 * l) + r
    return result

if __name__ == "__main__":
    field, moves_list = read_input(file)
    print_field(field)

    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    fps = 30
    frame_size = (len(field[0]) * grow_factor, len(field) * grow_factor)
    out = cv2.VideoWriter(f'./{out_file_name}.mp4', fourcc, fps, frame_size)
    gif_anim=[]

    img = array_to_image(field)
    gif_anim.append(img)
    cv2_image = pil_to_cv2(img)
    out.write(cv2_image)

    for moves in moves_list:
        for move in moves:
            field = do_move(field,move)
            #print_field(field)
            img = array_to_image(field)
            gif_anim.append(img)
            cv2_image = pil_to_cv2(img)
            out.write(cv2_image)
    out.release()
    gif_anim[0].save(f'./{out_file_name}.gif', save_all=True, append_images=gif_anim[1:],
                       optimize=False, duration=30, loop=0)

    print_field(field)
    print(f'Solution Part1: {sum_gps_coord(field)}')
    print(f'Runtime: {time()-start_time:.2f} s')