"""
--- Part Two ---

As you go to remove the virus from the infected nodes, it evolves to resist your
attempt.

Now, before it infects a clean node, it will weaken it to disable your defenses.
If it encounters an infected node, it will instead flag the node to be cleaned
in the future. So:

Clean nodes become weakened.
Weakened nodes become infected.
Infected nodes become flagged.
Flagged nodes become clean.
Every node is always in exactly one of the above states.

The virus carrier still functions in a similar way, but now uses the following
logic during its bursts of action:

Decide which way to turn based on the current node:
If it is clean, it turns left.
If it is weakened, it does not turn, and will continue moving in the same
    direction.
If it is infected, it turns right.
If it is flagged, it reverses direction, and will go back the way it came.
Modify the state of the current node, as described above.
The virus carrier moves forward one node in the direction it is facing.
Start with the same map (still using . for clean and # for infected) and still
    with the virus carrier starting in the middle and facing up.

Using the same initial state as the previous example, and drawing weakened as W
and flagged as F, the middle of the infinite grid looks like this, with the
virus carrier's position again marked with [ ]:

. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . # . . .
. . . #[.]. . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .

This is the same as before, since no initial nodes are weakened or flagged. The
virus carrier is on a clean node, so it still turns left, instead weakens the
node, and moves left:

. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . # . . .
. . .[#]W . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .

The virus carrier is on an infected node, so it still turns right, instead flags
the node, and moves up:

. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . .[.]. # . . .
. . . F W . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .

This process repeats three more times, ending on the previously-flagged node and
facing right:

. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . W W . # . . .
. . W[F]W . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .

Finding a flagged node, it reverses direction and cleans the node:

. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . W W . # . . .
. .[W]. W . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .

The weakened node becomes infected, and it continues in the same direction:

. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . W W . # . . .
.[.]# . W . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .

Of the first 100 bursts, 26 will result in infection. Unfortunately, another
feature of this evolved virus is speed; of the first 10000000 bursts, 2511944
will result in infection.

Given your actual map, after 10000000 bursts of activity, how many bursts cause
a node to become infected? (Do not count nodes that begin infected.)
"""
from itertools import cycle

from progressbar import ProgressBar

nodes = {k: dict(enumerate(list(v.rstrip())))
         for k, v in enumerate(open('input.txt').readlines())}

pos_y = 12
pos_x = 12
direction = cycle(['n', 'e', 's', 'w'])
facing = next(direction)

bursts = 10000000
infections = 0
bar = ProgressBar()
for i in bar(range(0, bursts)):
    if nodes[pos_y][pos_x] == '.':
        nodes[pos_y][pos_x] = 'W'
        next(direction)
        next(direction)
        facing = next(direction)
    elif nodes[pos_y][pos_x] == 'W':
        infections += 1
        nodes[pos_y][pos_x] = '#'
    elif nodes[pos_y][pos_x] == '#':
        nodes[pos_y][pos_x] = 'F'
        facing = next(direction)
    elif nodes[pos_y][pos_x] == 'F':
        nodes[pos_y][pos_x] = '.'
        next(direction)
        facing = next(direction)

    if facing == 'n':
        pos_y -= 1
    elif facing == 'e':
        pos_x += 1
    elif facing == 's':
        pos_y += 1
    elif facing == 'w':
        pos_x -= 1

    if pos_y not in nodes.keys():
        nodes[pos_y] = {}
    if pos_x not in nodes[pos_y].keys():
        nodes[pos_y][pos_x] = '.'

for i in sorted(nodes):
    for j in sorted(nodes[i]):
        if i == pos_y and j == pos_x:
            print('x', end='')
        else:
            print(nodes[i][j], end='')
    print()

print(infections)
