"""Die Richtung eines Etagenwechsels aus der Karte lesen.

Die Karte markiert Treppen, Leitern und Loecher als 'accessPoint'. Das
ist die einzige verlaessliche Quelle: Aus zwei Wegpunkten allein ist die
Richtung nicht ableitbar, sobald der Sprung diagonal aussieht.
"""

import numpy as np
import pytest

from src.repositories.radar import core as radar


WELT_X, WELT_Y = 31744, 30976
BODEN = 153


@pytest.fixture
def karte(mocker):
    """Eine kleine leere Etage 8, in die man Zugangspunkte setzen kann."""
    etagen = [np.full((40, 40), BODEN, dtype=np.uint8) for _ in range(16)]
    mocker.patch.object(radar, 'floorsImgs', etagen)
    return etagen


def _setze(karte, koordinate):
    karte[koordinate[2]][koordinate[1] - WELT_Y, koordinate[0] - WELT_X] = \
        radar.ZUGANGSPUNKT


def test_zugangspunkt_im_westen(karte):
    """Der Fall aus dem Depot von Thais."""
    _setze(karte, (WELT_X + 20, WELT_Y + 20, 8))

    assert radar.getFloorChangeDirection((WELT_X + 21, WELT_Y + 20, 8)) == 'west'


@pytest.mark.parametrize(('versatz', 'erwartet'), [
    ((0, -1), 'north'),
    ((0, 1), 'south'),
    ((-1, 0), 'west'),
    ((1, 0), 'east'),
])
def test_alle_vier_richtungen(karte, versatz, erwartet):
    mitte = (WELT_X + 20, WELT_Y + 20, 8)
    _setze(karte, (mitte[0] + versatz[0], mitte[1] + versatz[1], 8))

    assert radar.getFloorChangeDirection(mitte) == erwartet


def test_ohne_zugangspunkt_keine_antwort(karte):
    assert radar.getFloorChangeDirection((WELT_X + 20, WELT_Y + 20, 8)) is None


def test_zwei_zugangspunkte_sind_nicht_eindeutig(karte):
    """Lieber keine Antwort als eine geratene."""
    mitte = (WELT_X + 20, WELT_Y + 20, 8)
    _setze(karte, (mitte[0] - 1, mitte[1], 8))
    _setze(karte, (mitte[0], mitte[1] - 1, 8))

    assert radar.getFloorChangeDirection(mitte) is None


def test_diagonal_zaehlt_nicht(karte):
    """Gedrueckt werden nur die vier Pfeiltasten."""
    mitte = (WELT_X + 20, WELT_Y + 20, 8)
    _setze(karte, (mitte[0] - 1, mitte[1] - 1, 8))

    assert radar.getFloorChangeDirection(mitte) is None


def test_nur_die_eigene_etage_zaehlt(karte):
    mitte = (WELT_X + 20, WELT_Y + 20, 8)
    _setze(karte, (mitte[0] - 1, mitte[1], 7))

    assert radar.getFloorChangeDirection(mitte) is None


def test_ohne_koordinate_und_bei_unbekannter_etage(karte):
    assert radar.getFloorChangeDirection(None) is None
    assert radar.getFloorChangeDirection((WELT_X + 20, WELT_Y + 20, 99)) is None


def test_am_kartenrand_kein_absturz(karte):
    """Am aeussersten Feld darf der Blick nach draussen nicht knallen."""
    assert radar.getFloorChangeDirection((WELT_X, WELT_Y, 8)) is None
