import pytest
import json

from flowtimer.Phase import Phase
from flowtimer.RecurringPhaseSequence import RecurringPhaseSequence


class TestRecurringPhaseSequence():

    @pytest.fixture
    def recurring_phase_sequence(self):
        phase_list = [Phase("Huddle", 10), Phase("Tasking", 5),
                      Phase("Work", 45), Phase("Break", 15)]
        return RecurringPhaseSequence(phase_list, 3)

    def test_from_json(self):
        json_string = RecurringPhaseSequence.default_json_string()
        sequence = RecurringPhaseSequence.from_json(json_string)
        assert isinstance(sequence, RecurringPhaseSequence)
        assert sequence.initial_repetitions == 3
        assert len(sequence.phase_list) == 4
        assert sequence.phase_list[0].title == "Huddle"

    def test_to_json(self, recurring_phase_sequence):
        json_string = recurring_phase_sequence.to_json()
        data = json.loads(json_string)
        assert data['state'] == "initial"
        assert data['initial_repetitions'] == 3
        assert data['passes_left'] == 3
        assert len(data['phase_list']) == 4

    def test_initial_state(self, recurring_phase_sequence):
        assert recurring_phase_sequence.state == "initial"
        assert recurring_phase_sequence.current_phase.title == "Huddle"
        assert recurring_phase_sequence.passes_left == 3

    def test_current_phase_number(self, recurring_phase_sequence):
        assert recurring_phase_sequence.current_phase_number() == 0
        recurring_phase_sequence.tick(10)
        assert recurring_phase_sequence.current_phase_number() == 1

    def test_phases_left_in_pass(self, recurring_phase_sequence):
        assert recurring_phase_sequence.phases_left_in_pass() == 3
        recurring_phase_sequence.tick(10)
        assert recurring_phase_sequence.phases_left_in_pass() == 2

    def test_upcoming_phases_in_pass(self, recurring_phase_sequence):
        upcoming = recurring_phase_sequence.upcoming_phases_in_pass()
        assert len(upcoming) == 3
        assert upcoming[0].title == "Tasking"

    def test_ticks_left(self, recurring_phase_sequence):
        total_ticks = (sum([phase.initial_ticks for phase in recurring_phase_sequence.phase_list]) *
                       recurring_phase_sequence.initial_repetitions)

        assert recurring_phase_sequence.ticks_left == total_ticks
        recurring_phase_sequence.tick(10)
        assert recurring_phase_sequence.ticks_left == (total_ticks - 10)

    def test_finished(self, recurring_phase_sequence):
        assert not recurring_phase_sequence.finished()
        for _ in range(3):
            for phase in recurring_phase_sequence.phase_list:
                recurring_phase_sequence.tick(phase.initial_ticks)
        assert recurring_phase_sequence.finished()

    def test_abort(self, recurring_phase_sequence):
        recurring_phase_sequence.abort()
        assert recurring_phase_sequence.state == "finished"
        assert recurring_phase_sequence.current_phase.finished()

    def test_tick_progression(self, recurring_phase_sequence):
        recurring_phase_sequence.tick(10)
        assert recurring_phase_sequence.current_phase.title == "Tasking"
        assert recurring_phase_sequence.passes_left == 3

        recurring_phase_sequence.tick(5)
        assert recurring_phase_sequence.current_phase.title == "Work"
        assert recurring_phase_sequence.passes_left == 3

        recurring_phase_sequence.tick(45)
        assert recurring_phase_sequence.current_phase.title == "Break"
        assert recurring_phase_sequence.passes_left == 3

        recurring_phase_sequence.tick(15)
        assert recurring_phase_sequence.current_phase.title == "Huddle"
        assert recurring_phase_sequence.passes_left == 2

    def test_unrolled(self, recurring_phase_sequence):
        unrolled_phases = recurring_phase_sequence.unrolled()
        assert len(unrolled_phases) == 12
        assert unrolled_phases[0].title == "Huddle"
        assert unrolled_phases[-1].title == "Break"
