from pprint import pprint as pp

from anim import Animate
import shared
import matrix

MATRIX_SIZE = 400
ATRIX_SIZE = 40  # sample
HALF = MATRIX_SIZE // 2

H = [HALF, HALF]
T = [HALF, HALF]


# returns (x,y) - so remember to take dx,dy lower
DIRS = {
    "U": matrix.M_U,  # (0, -1)
    "D": matrix.M_D,
    "L": matrix.M_L,
    "R": matrix.M_R,
    "UR": matrix.M_UR,  # (+1, -1)
    "DR": matrix.M_DR,
    "UL": matrix.M_UL,
    "DL": matrix.M_DL,
}


def part1(steps):
    field = matrix.matrix_of_size(MATRIX_SIZE, MATRIX_SIZE)
    anim = Animate(field, day="09")

    for direction, amount in steps:
        # move HEAD
        amount = int(amount)
        for x in range(amount):

            dx, dy = DIRS[direction]
            H[0] += dy
            H[1] += dx
            HY, bX = H
            # head is in new position
            kY, kX = T
            field[kY][kX] = 1  # 'T'

            # Check if same
            if kY == HY and kX == bX:
                continue
            touching = False
            for _, d in DIRS.items():
                dx, dy = d
                t_y, t_x = H[0] + dy, H[1] + dx
                if kY == t_y and kX == t_x:
                    touching = True
                    break
            if touching:
                continue

            # assume the same row/column, no movement needed
            tY = 0
            tX = 0

            # if Head X is less than Tail X, move Tail X 1 left
            if bX < kX:
                tX = -1
            # if Head X is greater than Tail X, move Tail X 1 left
            elif bX > kX:
                tX = 1

            # if Head Y is less than Tail Y, move Tail Y 1 up
            if HY < kY:
                tY = -1
            # if Head Y is greater than Tail Y, move Tail Y 1 down
            elif HY > kY:
                tY = 1

            T[0] += tY
            T[1] += tX
            anim.add_frame(field)

        field[T[0]][T[1]] = 1  # mark visited tails
    print(matrix.sum_matrix(field))
    anim.animate()


def part2(steps):
    field = matrix.matrix_of_size(MATRIX_SIZE, MATRIX_SIZE)
    anim = Animate(field, day="09")
    S = [
        [HALF, HALF],
    ]  # HEAD ONLY
    _cur_frame = 0
    for x in range(9):
        S.append([HALF, HALF])

    for direction, amount in steps:
        # move HEAD
        amount = int(amount)
        for x in range(amount):
            HEAD_dx, HEAD_dy = DIRS[direction]
            S[0][0] += HEAD_dy
            S[0][1] += HEAD_dx
            # print(HEAD_dy,HEAD_dx, S)
            # HEAD MOVED one step

            for knot_idx, _ in enumerate(S):
                if knot_idx == 0:
                    # Skip Head
                    continue
                knot = S[knot_idx]
                kY, kX = knot

                bY, bX = S[knot_idx - 1]

                # Check if same
                if kY == bY and kX == bX:
                    continue

                touching = False
                for _, d in DIRS.items():
                    dx, dy = d
                    t_y, t_x = S[knot_idx - 1][0] + dy, S[knot_idx - 1][1] + dx
                    if kY == t_y and kX == t_x:
                        touching = True
                        break
                if touching:
                    continue

                # assume the same row/column, no movement needed
                tY, tX = 0, 0

                # if Head X is less than Tail X, move Tail X 1 left
                if bX < kX:
                    tX = -1
                # if Head X is greater than Tail X, move Tail X 1 left
                elif bX > kX:
                    tX = 1

                # if Head Y is less than Tail Y, move Tail Y 1 up
                if bY < kY:
                    tY = -1
                # if Head Y is greater than Tail Y, move Tail Y 1 down
                elif bY > kY:
                    tY = 1

                S[knot_idx][0] += tY
                S[knot_idx][1] += tX
                if _cur_frame % 25 == 0:
                    anim.add_frame(field)
                _cur_frame += 1
            field[S[-1][0]][S[-1][1]] = 1  # mark visited tails
    print(matrix.sum_matrix(field))
    anim.animate()


def main():
    rows = [x.split(" ") for x in shared.load_rows(9)]
    # part1(rows)
    part2(rows)


if __name__ == "__main__":
    main()
