package cz.jzitnik.events.handlers;

import com.googlecode.lanterna.TerminalPosition;
import com.googlecode.lanterna.input.KeyStroke;
import cz.jzitnik.annotations.EventHandler;
import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.events.PlayerMoveEvent;
import cz.jzitnik.events.RerenderScreen;
import cz.jzitnik.events.RoomChangeEvent;
import cz.jzitnik.game.GameRoom;
import cz.jzitnik.game.GameState;
import cz.jzitnik.game.Player;
import cz.jzitnik.game.ResourceManager;
import cz.jzitnik.game.utils.RoomCords;
import cz.jzitnik.states.ScreenBuffer;
import cz.jzitnik.states.TerminalState;
import cz.jzitnik.utils.DependencyManager;
import cz.jzitnik.utils.RerenderUtils;
import cz.jzitnik.utils.events.AbstractEventHandler;
import cz.jzitnik.utils.events.EventManager;
import lombok.extern.slf4j.Slf4j;

import java.awt.image.BufferedImage;

@Slf4j
@EventHandler(PlayerMoveEvent.class)
public class PlayerMoveEventHandler extends AbstractEventHandler<PlayerMoveEvent> {
    public PlayerMoveEventHandler(DependencyManager dm) {
        super(dm);
    }

    @InjectState
    private GameState gameState;

    @InjectDependency
    private EventManager eventManager;

    @InjectState
    private TerminalState terminalState;

    @InjectState
    private ScreenBuffer screenBuffer;

    @InjectDependency
    private ResourceManager resourceManager;

    @Override
    public void handle(PlayerMoveEvent event) {
        KeyStroke keyStroke = event.getKeyStroke();
        Player player = gameState.getPlayer();
        RoomCords playerCords = player.getPlayerCords();

        int moveStep = 3;

        int originalPlayerX = playerCords.getX();
        int originalPlayerY = playerCords.getY();
        switch (keyStroke.getCharacter()) {
            case 'w' -> {
                if (originalPlayerY <= 10) {
                    if (originalPlayerX >= 80 && originalPlayerX <= 105) {
                        eventManager.emitEvent(new RoomChangeEvent(FullRoomDrawHandler.DoorPosition.TOP));
                    }
                    return;
                }
                playerCords.updateCords(player.getPlayerCords().getX(), playerCords.getY() - moveStep);
            }
            case 'a' -> {
                if (originalPlayerX <= 30) {
                    if (originalPlayerY >= 35 && originalPlayerY <= 65) {
                        eventManager.emitEvent(new RoomChangeEvent(FullRoomDrawHandler.DoorPosition.LEFT));
                    }
                    return;
                }
                playerCords.updateCords(player.getPlayerCords().getX() - moveStep, playerCords.getY());
            }
            case 's' -> {
                if (originalPlayerY >= 110) {
                    if (originalPlayerX >= 75 && originalPlayerX <= 105) {
                        eventManager.emitEvent(new RoomChangeEvent(FullRoomDrawHandler.DoorPosition.BOTTOM));
                    }
                    return;
                }
                playerCords.updateCords(player.getPlayerCords().getX(), playerCords.getY() + moveStep);
            }
            case 'd' -> {
                if (originalPlayerX >= 155) {
                    if (originalPlayerY >= 40 && originalPlayerY <= 60) {
                        eventManager.emitEvent(new RoomChangeEvent(FullRoomDrawHandler.DoorPosition.RIGHT));
                    }
                    return;
                }
                playerCords.updateCords(player.getPlayerCords().getX() + moveStep, playerCords.getY());
            }
        }
        int newPlayerX = playerCords.getX();
        int newPlayerY = playerCords.getY();
        log.debug("x: {}, y: {}", newPlayerX, newPlayerY);
        BufferedImage playerTexture = RerenderUtils.getPlayer(resourceManager, player);
        int forStartX = Math.min(originalPlayerX, newPlayerX);
        int forStartY = Math.min(originalPlayerY, newPlayerY);
        int forEndX = Math.max(originalPlayerX, newPlayerX) + playerTexture.getWidth();
        int forEndY = Math.max(originalPlayerY, newPlayerY) + playerTexture.getHeight();

        GameRoom currentRoom = gameState.getCurrentRoom();
        BufferedImage room = resourceManager.getResource(currentRoom.getTexture());
        var start = RerenderUtils.getStart(room, terminalState.getTerminalScreen().getTerminalSize());
        int startX = start.getX();
        int startY = start.getY();

        RerenderUtils.rerenderPart(forStartX, forEndX, forStartY, forEndY, startX, startY, currentRoom, room, player, playerTexture, screenBuffer, resourceManager);

        eventManager.emitEvent(new RerenderScreen(
                new RerenderScreen.ScreenPart(
                        new TerminalPosition(forStartX + startX, forStartY + startY),
                        new TerminalPosition(forEndX + 1 + startX, forEndY + startY)
                )
        ));
    }
}
