from asteracer import *


def load_asteroid_graph(path: str):
    with open(path) as f:
        contents = [
            line
            for line in f.read().splitlines()
            if not line.startswith("#") and line.strip() != ""
        ]

        n_racer, n_asteroid, n_goal, m = list(map(int, contents[0].split()))

        vertices = []
        edges = []
        vertex_objects = []

        # Load vertices
        for i in range(1, 1 + n_racer + n_asteroid + n_goal):
            line = contents[i + 1].split()

            vertices.append((int(line[0]), int(line[1])))

            if 0 <= i < n_racer:
                vertex_objects.append(("S", i))
            elif n_racer <= i < n_asteroid:
                vertex_objects.append(("A", int(line[2])))
            elif n_asteroid <= i < n_goal:
                vertex_objects.append(("G", int(line[2])))

        # Load edges
        for i in range(i, i + m):
            line = contents[i + 1].split()

            edges.append((int(line[0]), int(line[1])))

    return vertices, edges, vertex_objects


if __name__ == "__main__":
    simulation = Simulation.load(f"../mapy/test.txt")

    print(f"Startovní pozice: {simulation.racer.x} {simulation.racer.y}")
    print(f"Počet asteroidů: {len(simulation.asteroids)}")
    print(f"Počet cílů: {len(simulation.goals)}")
    print()

    tick = 0
    print("Letím doprava...")
    while True:
        result = simulation.tick(Instruction(127, 0))

        if result & TickFlag.COLLIDED:
            print(f"Narazili jsme po {tick} instrukcích! Au...")
            print(f"Aktuální pozice: {simulation.racer.x} {simulation.racer.y}")
            print()
            break

        tick += 1

    print("Letím dolů (je tam gól)...")
    while True:
        result = simulation.tick(Instruction(0, 127))

        if result & TickFlag.GOAL_REACHED:
            print(f"Sebrali jsme gól po {tick} instrucích!")
            print(f"Góly sesbírány: {simulation.reached_goals}")
            print(f"Aktuální pozice: {simulation.racer.x} {simulation.racer.y}")
            print()
            break

        tick += 1

# posbíráme zbývající cíle tak, že k nim poletíme přímou čarou
    for _ in range(simulation.reached_goals.count(False)):
        nearest_goal = None
        nearest_goal_distance = float('inf')

        for i, reached in enumerate(simulation.reached_goals):
            if not reached:
                goal = simulation.goals[i]
                distance = euclidean_distance(goal.x, goal.y, simulation.racer.x, simulation.racer.y)

                if distance < nearest_goal_distance:
                    nearest_goal_distance = distance
                    nearest_goal = goal

        print("Letíme k nejbližšímu cíli přímou čarou...")
        collided_count = 0
        while True:
            instruction = Instruction(
                nearest_goal.x - simulation.racer.x,
                nearest_goal.y - simulation.racer.y,
            )

            result = simulation.tick(instruction)

            if result & TickFlag.COLLIDED:
                collided_count += 1

            if result & TickFlag.GOAL_REACHED:
                print(f"Sebrali jsme další gól po {tick} instrucích!")
                print(f"Počet nárazů po cestě: {collided_count}")
                print(f"Góly sesbírány: {simulation.reached_goals}")
                print()
                break

            tick += 1

    print(f"Hotovo!")
    print()
    assert simulation.finished()

    print("Načítám graf...")
    # - vertices jsou (x, y) pozice vrcholů 
    # - edges jsou (u, v) dvojice vrcholů tvořících hranu
    # - vertex_objects jsou dvojice (typ, index), kde
    #   typ je typ objektu vrcholu ('A' asteroid, 'G' gól a 'S' loď)
    #   a index je kolikátý je to objekt (t.j. kolikátý asteroid, gól, apod.)
    vertices, edges, vertex_objects = load_asteroid_graph("../grafy/test.txt")

    print(f"Má {len(vertices)} vrcholů a {len(edges)} hran, vypisuji prvních 5:")
    print(f"-> vrcholy: {vertices[:5]}")
    print(f"-> hrany: {edges[:5]}")
    print(f"-> objekty: {vertex_objects[:5]}")