import numpy as np
from src.gameplay.core.tasks.depositItems import DepositItemsTask
from src.gameplay.core.tasks.dragItems import DragItemsTask
from src.gameplay.core.tasks.expandBackpack import ExpandBackpackTask
from src.gameplay.core.tasks.goToFreeDepot import GoToFreeDepotTask
from src.gameplay.core.tasks.openBackpack import OpenBackpackTask
from src.gameplay.core.tasks.openDepot import OpenDepotTask
from src.gameplay.core.tasks.openLocker import OpenLockerTask
from src.gameplay.core.tasks.setNextWaypoint import SetNextWaypointTask
from src.gameplay.core.tasks.takeSupplies import TakeSuppliesTask
from src.repositories.inventory.core import images


context = {
    'ng_backpacks': {
        'main': 'Brocade Backpack',
        'loot': 'Beach Backpack',
    }
}
waypoint = {'coordinate': (1, 2, 3)}


def test_should_test_default_params():
    task = DepositItemsTask(waypoint)
    assert task.name == 'depositItems'
    assert task.isRootTask == True
    assert task.delayBeforeStart == 1
    assert task.delayAfterComplete == 1


def test_onBeforeStart():
    """Depot oeffnen, dann jeden Rucksack einzeln leeren.

    Ein ganzer Rucksack wird nie verschoben - frueher wanderte der
    Loot-Rucksack als Ganzes in die Ablage. Das setzt einen zweiten
    Rucksack voraus und nimmt die Kontrolle darueber, was abgelegt wird.
    """
    task = DepositItemsTask(waypoint)
    assert task.onBeforeStart(context) == context
    assert len(task.tasks) == 12
    for schritt in task.tasks:
        assert schritt.parentTask == task
        assert schritt.rootTask == task

    assert isinstance(task.tasks[0], GoToFreeDepotTask)
    assert isinstance(task.tasks[1], OpenLockerTask)
    assert isinstance(task.tasks[2], OpenDepotTask)

    # Zuerst der Loot-Rucksack, dann der Haupt-Rucksack.
    for versatz, schluessel in ((3, 'loot'), (7, 'main')):
        name = context['ng_backpacks'][schluessel]
        assert isinstance(task.tasks[versatz], OpenBackpackTask)
        assert task.tasks[versatz].backpack == name
        assert isinstance(task.tasks[versatz + 1], ExpandBackpackTask)
        assert task.tasks[versatz + 1].backpack == name
        ziehen = task.tasks[versatz + 2]
        assert isinstance(ziehen, DragItemsTask)
        assert np.array_equal(
            ziehen.containerBarImage, images['containersBars'][name])
        assert np.array_equal(
            ziehen.targetContainerImage, images['slots']['depot chest 2'])
        # Danach wird geprueft, ob Ausruestung fehlt und zurueckgeholt.
        assert isinstance(task.tasks[versatz + 3], TakeSuppliesTask)

    assert isinstance(task.tasks[11], SetNextWaypointTask)


def test_only_one_backpack_is_visited_once():
    """Sind Haupt- und Loot-Rucksack derselbe, wird er nicht doppelt geleert."""
    task = DepositItemsTask(waypoint)
    task.onBeforeStart({'ng_backpacks': {
        'main': 'Brocade Backpack', 'loot': 'Brocade Backpack'}})

    assert len(task.tasks) == 8
    assert sum(isinstance(t, DragItemsTask) for t in task.tasks) == 1


def test_backpack_without_template_is_skipped():
    """Ohne Vorlage laesst sich ein Rucksack nicht ansteuern.

    Er wird uebersprungen, statt den ganzen Ablauf scheitern zu lassen -
    die uebrigen Rucksaecke sollen trotzdem eingelagert werden.
    """
    task = DepositItemsTask(waypoint)
    task.onBeforeStart({'ng_backpacks': {
        'main': 'Brocade Backpack', 'loot': 'Gibt Es Nicht'}})

    assert sum(isinstance(t, DragItemsTask) for t in task.tasks) == 1
    assert task.tasks[3].backpack == 'Brocade Backpack'


def test_without_backpacks_only_the_depot_is_opened():
    task = DepositItemsTask(waypoint)
    task.onBeforeStart({})

    assert len(task.tasks) == 4
    assert not any(isinstance(t, DragItemsTask) for t in task.tasks)
