package de.miaurizius.jgame2d.core.handlers;

import de.miaurizius.jgame2d.core.Boot;
import de.miaurizius.jgame2d.core.GamePanel;
import de.miaurizius.jgame2d.core.enums.Direction;
import de.miaurizius.jgame2d.core.enums.GameState;
import de.miaurizius.jgame2d.core.enums.Map;
import de.miaurizius.jgame2d.entity.Entity;

import java.awt.*;
import java.util.logging.Level;

public class EventHandler {

    GamePanel panel;
    EventRect[][][] eventRect;
    Entity eventMaster; //Like a "voice of god"
    public int prevEventX, prevEventY;
    boolean canTouchEvent = true;

    // TMP VARS FOR TRANSITION
    public int tempCol, tempRow;
    public Map tempMap;

    public EventHandler(GamePanel panel) {
        this.panel = panel;
        eventMaster = new Entity(panel);
        eventRect = new EventRect[Map.values().length][panel.maxWorldCol][panel.maxWorldRow];

        int map = 0;
        int col = 0;
        int row = 0;
        while(map < Map.values().length && col < panel.maxWorldCol && row < panel.maxWorldRow) {
            eventRect[map][col][row] = new EventRect();
            eventRect[map][col][row].x = 23;
            eventRect[map][col][row].y = 23;
            eventRect[map][col][row].width = 2;
            eventRect[map][col][row].height = 2;
            eventRect[map][col][row].eventRectDefaultX = eventRect[map][col][row].x;
            eventRect[map][col][row].eventRectDefaultY = eventRect[map][col][row].y;
            col++;
            if(col == panel.maxWorldCol) {
                col = 0;
                row++;
                if(row == panel.maxWorldRow) {
                    row = 0;
                    map++;
                }
            }
        }

        setDialogue();
    }

    public void setDialogue() {
        eventMaster.dialogue[0][0] = "You have fallen into a pit!";
        eventMaster.dialogue[1][0] = "You saved your progress!";
    }
    public void checkEvent() {
        // Check if the player char is more than 1 tile away from the last event
        int xDistance = Math.abs(panel.player.worldX - prevEventX); //return absolute number
        int yDistance = Math.abs(panel.player.worldY - prevEventY);
        int distance = Math.max(xDistance, yDistance); //picks greater number
        if(distance > panel.tileSize) canTouchEvent = true;
        if(!canTouchEvent) return;

        // PIT/POOL TESTS
        if(hit(Map.OVERWORLD, 27,16, Direction.RIGHT)) damagePit();
        else if(hit(Map.OVERWORLD, 23,12, null)) healingPool();

        // HUT
        else if(hit(Map.OVERWORLD, 10, 39, null)) changeMap(Map.HUT, 12, 13);
        else if(hit(Map.HUT, 12, 13, null)) changeMap(Map.OVERWORLD, 10, 39);

        // ADVANCED SPEAKING
        else if(hit(Map.HUT, 12, 9, Direction.UP)) speak(panel.npc[Map.HUT.getIndex()][0]);
    }

    /**
     * @param reqDirection Set to null if no direction is required
     */
    private boolean hit(Map map, int eventCol, int eventRow, Direction reqDirection) {
        boolean hit = false;
        panel.player.solidArea.x = panel.player.worldX + panel.player.solidArea.x;
        panel.player.solidArea.y = panel.player.worldY + panel.player.solidArea.y;
        eventRect[map.getIndex()][eventCol][eventRow].x = eventCol*panel.tileSize + eventRect[map.getIndex()][eventCol][eventRow].x;
        eventRect[map.getIndex()][eventCol][eventRow].y = eventRow*panel.tileSize + eventRect[map.getIndex()][eventCol][eventRow].y;
        if(
                panel.player.solidArea.intersects(eventRect[map.getIndex()][eventCol][eventRow]) &&
                (reqDirection == null || panel.player.direction == reqDirection) &&
                !eventRect[map.getIndex()][eventCol][eventRow].eventDone
        ) {
            hit = true;
            prevEventX = panel.player.worldX;
            prevEventY = panel.player.worldY;
        }
        panel.player.solidArea.x = panel.player.solidAreaDefaultX;
        panel.player.solidArea.y = panel.player.solidAreaDefaultY;
        eventRect[map.getIndex()][eventCol][eventRow].x = eventRect[map.getIndex()][eventCol][eventRow].eventRectDefaultX;
        eventRect[map.getIndex()][eventCol][eventRow].y = eventRect[map.getIndex()][eventCol][eventRow].eventRectDefaultY;
        if(panel.currentMap != map) hit = false;
        return hit;
    }

    private void damagePit() {
        panel.playSE(6);
        panel.player.life -= 1;
        eventMaster.startDialogue(eventMaster,0);
        canTouchEvent = false;
    }
    private void healingPool() {
        if(!panel.keyH.spacePressed) return;
        panel.gameState = GameState.DIALOGUE;
        panel.player.attackCancel = true;
        panel.playSE(2);
        eventMaster.startDialogue(eventMaster,1);
        //panel.player.life = panel.player.maxLife;
        canTouchEvent = false;
        panel.assetSetter.setMonster();
        try {
            panel.saveLoad.save();
        } catch (Exception e) {
            Boot.logger.log(Level.SEVERE, "Saving game failed!", e);
        }
    }
    private void changeMap(Map map, int col, int row) {
        panel.gameState = GameState.TRANSITION;
        tempMap = map;
        tempCol = col;
        tempRow = row;
        canTouchEvent = false;
        panel.playSE(13);
    }
    private void speak(Entity entity) {
        if(!panel.keyH.spacePressed) return;
        panel.gameState = GameState.DIALOGUE;
        panel.player.attackCancel = true;
        entity.speak();
    }

    static private class EventRect extends Rectangle {
        int eventRectDefaultX, eventRectDefaultY;
        boolean eventDone = false;
    }
}

