import networkx as nx

from funtracks.actions import AddNode
from funtracks.actions.action_history import ActionHistory
from funtracks.data_model import SolutionTracks

# https://github.com/zaboople/klonk/blob/master/TheGURQ.md


def test_action_history():
    history = ActionHistory()
    tracks = SolutionTracks(nx.DiGraph(), ndim=3, tracklet_attr="track_id")
    pos = [0, 1]
    action1 = AddNode(tracks, node=0, attributes={"time": 0, "pos": pos, "track_id": 1})

    # empty history has no undo or redo
    assert not history.undo()
    assert not history.redo()

    # add an action to the history
    history.add_new_action(action1)
    # undo the action
    assert history.undo()
    assert tracks.graph.number_of_nodes() == 0
    assert len(history.undo_stack) == 1
    assert len(history.redo_stack) == 1
    assert history._undo_pointer == -1

    # no more actions to undo
    assert not history.undo()

    # redo the action
    assert history.redo()
    assert tracks.graph.number_of_nodes() == 1
    assert len(history.undo_stack) == 1
    assert len(history.redo_stack) == 0
    assert history._undo_pointer == 0

    # no more actions to redo
    assert not history.redo()

    # undo and then add new action
    assert history.undo()
    action2 = AddNode(tracks, node=10, attributes={"time": 10, "pos": pos, "track_id": 2})
    history.add_new_action(action2)
    assert tracks.graph.number_of_nodes() == 1
    # there are 3 things on the stack: action1, action1's inverse, and action 2
    assert len(history.undo_stack) == 3
    assert len(history.redo_stack) == 0
    assert history._undo_pointer == 2

    # undo back to after action 1
    assert history.undo()
    assert history.undo()
    assert tracks.graph.number_of_nodes() == 1

    assert len(history.undo_stack) == 3
    assert len(history.redo_stack) == 2
    assert history._undo_pointer == 0
