import pygame
import sas_pygame as sas


# -----------------------------------
# Raster / Brett
# -----------------------------------

class Kachel:
    def __init__(self, x, y, bw, bh, farbe):
        self.x = x
        self.y = y
        self.rechteck = sas.Rectangle(x * bw, y * bh, bw, bh, farbe)


class Rasterflaeche:
    def __init__(self, nx, ny, pixel_breite, pixel_hoehe):
        self.anzahlKachelnX = nx
        self.anzahlKachelnY = ny
        self.kachelBreite = pixel_breite / nx
        self.kachelHoehe = pixel_hoehe / ny

        self.kacheln = []
        for x in range(nx):
            zeile = []
            for y in range(ny):
                farbe = "white" if (x + y) % 2 == 0 else "black"
                zeile.append(Kachel(x, y, self.kachelBreite, self.kachelHoehe, farbe))
            self.kacheln.append(zeile)

    def istInnen(self, pos):
        x, y = pos
        return 0 <= x < self.anzahlKachelnX and 0 <= y < self.anzahlKachelnY


# -----------------------------------
# Spielstein (Drag im Hauptloop)
# -----------------------------------

class Spielstein:
    def __init__(self, feld, x, y, farbe):
        self.feld = feld
        self.position = (x, y)
        self.dragging = False
        self._last_mouse = None

        r = (feld.kachelBreite - 10) / 2
        self.shape = sas.Circle(
            x * feld.kachelBreite + 5,
            y * feld.kachelHoehe + 5,
            r,
            farbe
        )

    def setzePosition(self, pos):
        self.position = pos
        self.shape.moveTo(
            pos[0] * self.feld.kachelBreite + 5,
            pos[1] * self.feld.kachelHoehe + 5
        )

    def start_drag(self, mx, my):
        self.dragging = True
        self._last_mouse = (mx, my)

    def drag_update(self, mx, my):
        if not self.dragging or self._last_mouse is None:
            return
        lx, ly = self._last_mouse
        self.shape.move(mx - lx, my - ly)
        self._last_mouse = (mx, my)

    def stop_drag_and_snap(self, mx, my):
        self.dragging = False
        self._last_mouse = None

        bw = self.feld.kachelBreite
        bh = self.feld.kachelHoehe

        tx = int(mx // bw)
        ty = int(my // bh)

        tx = max(0, min(self.feld.anzahlKachelnX - 1, tx))
        ty = max(0, min(self.feld.anzahlKachelnY - 1, ty))
        return (tx, ty)


# -----------------------------------
# Spielfeld + Regeln
# -----------------------------------

class Spielfeld(Rasterflaeche):
    def __init__(self):
        super().__init__(8, 8, 400, 400)

        self.wolf = Spielstein(self, 4, 7, "red")
        self.schafe = [
            Spielstein(self, 1, 0, "yellow"),
            Spielstein(self, 3, 0, "yellow"),
            Spielstein(self, 5, 0, "yellow"),
            Spielstein(self, 7, 0, "yellow"),
        ]

    def feldBelegt(self, pos):
        if pos == self.wolf.position:
            return True
        return any(pos == s.position for s in self.schafe)

    def zugZulaessig(self, stein, neuePos):
        if not self.istInnen(neuePos):
            return False
        if self.feldBelegt(neuePos):
            return False

        x0, y0 = stein.position
        x1, y1 = neuePos

        # Nur diagonal 1 Feld
        if abs(x1 - x0) != 1 or abs(y1 - y0) != 1:
            return False

        # Schafe dürfen nur vorwärts (nach unten: y wird größer)
        if stein in self.schafe and y1 <= y0:
            return False

        # Wolf darf vorwärts und zurück -> keine zusätzliche Regel
        return True

    # --- Gewinnbedingungen ---
    def wolf_hat_gewonnen(self):
        # Wolf gewinnt, wenn er auf der letzten Reihe (oben) ist
        return self.wolf.position[1] == 0

    def wolf_hat_zug(self):
        x, y = self.wolf.position
        ziele = [(x - 1, y - 1), (x + 1, y - 1), (x - 1, y + 1), (x + 1, y + 1)]
        for z in ziele:
            if self.zugZulaessig(self.wolf, z):
                return True
        return False

    def schafe_haben_gewonnen(self):
        # Schafe gewinnen, wenn Wolf blockiert ist
        return not self.wolf_hat_zug()


# -----------------------------------
# Hauptprogramm
# -----------------------------------

def main():
    view = sas.createView(400, 450, "white", "Wolf und Schafe")
    feld = Spielfeld()

    text = sas.Text(10, 410, "Wolf ist am Zug")
    text.setFont(20)

    wolfAmZug = True
    game_over = False

    selected = None
    start_pos = None
    ignore_until_release = False

    while view.running:
        view.step()

        if game_over:
            continue

        mx, my = view.getMouseX(), view.getMouseY()

        # -------------------------
        # Auswahl bei Mausklick
        # -------------------------
        if view.mousePressed() and selected is None and not ignore_until_release:

            kandidaten = [feld.wolf] if wolfAmZug else feld.schafe
            getroffen = False

            for stein in kandidaten:
                if stein.shape.hit_test((mx, my)):
                    selected = stein
                    start_pos = stein.position
                    stein.start_drag(mx, my)
                    getroffen = True
                    break

            if not getroffen:
                # Falsche Figur oder leeres Feld
                ignore_until_release = True

        # -------------------------
        # Drag während gedrückt
        # -------------------------
        if selected is not None and view.mouseDown:
            selected.drag_update(mx, my)

        # -------------------------
        # Loslassen der Maus
        # -------------------------
        if view.mouseReleased():
            ignore_until_release = False

            if selected is not None:
                ziel = selected.stop_drag_and_snap(mx, my)

                if feld.zugZulaessig(selected, ziel):
                    selected.setzePosition(ziel)
                    wolfAmZug = not wolfAmZug
                    text.setText("Wolf ist am Zug" if wolfAmZug else "Schafe sind am Zug")

                    # ---- Gewinn prüfen ----
                    if feld.wolf_hat_gewonnen():
                        text.setText("Wolf hat gewonnen!")
                        game_over = True

                    elif feld.schafe_haben_gewonnen():
                        text.setText("Schafe haben gewonnen!")
                        game_over = True
                else:
                    # ungültiger Zug -> zurück
                    selected.setzePosition(start_pos)

                selected = None
                start_pos = None


main()
