package de.miaurizius.jgame2d.core.handlers;

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

public class CollisionHandler {

    GamePanel panel;

    public CollisionHandler(GamePanel panel) {
        this.panel = panel;
    }

    // WORLD COLLISION
    public void checkTile(Entity entity) {
        int entityLeftWorldX = entity.worldX + entity.solidArea.x;
        int entityRightWorldX = entity.worldX + entity.solidArea.x + entity.solidArea.width;
        int entityTopWorldY = entity.worldY + entity.solidArea.y;
        int entityBottomWorldY = entity.worldY + entity.solidArea.y + entity.solidArea.height;

        int entityLeftCol = entityLeftWorldX/panel.tileSize;
        int entityRightCol = entityRightWorldX/panel.tileSize;
        int entityTopRow = entityTopWorldY/panel.tileSize;
        int entityBottomRow = entityBottomWorldY/panel.tileSize;

        int tileNum1, tileNum2;

        // TEMP DIRECTION FOR KNOCKBACK
        Direction direction = entity.direction;
        if(entity.knockback) direction = entity.knockbackDirection;

        switch(direction) {
            case UP:
                entityTopRow = (entityTopWorldY - entity.speed)/panel.tileSize;
                tileNum1 = panel.tileM.mapTileNum[panel.currentMap.getIndex()][entityLeftCol][entityTopRow];
                tileNum2 = panel.tileM.mapTileNum[panel.currentMap.getIndex()][entityRightCol][entityTopRow];
                if(panel.tileM.tile[tileNum1].collision || panel.tileM.tile[tileNum2].collision) entity.collisionOn = true;
                break;
            case DOWN:
                entityBottomRow = (entityBottomWorldY + entity.speed)/panel.tileSize;
                tileNum1 = panel.tileM.mapTileNum[panel.currentMap.getIndex()][entityLeftCol][entityBottomRow];
                tileNum2 = panel.tileM.mapTileNum[panel.currentMap.getIndex()][entityRightCol][entityBottomRow];
                if(panel.tileM.tile[tileNum1].collision || panel.tileM.tile[tileNum2].collision) entity.collisionOn = true;
                break;
            case LEFT:
                entityLeftCol = (entityLeftWorldX - entity.speed)/panel.tileSize;
                tileNum1 = panel.tileM.mapTileNum[panel.currentMap.getIndex()][entityLeftCol][entityTopRow];
                tileNum2 = panel.tileM.mapTileNum[panel.currentMap.getIndex()][entityLeftCol][entityBottomRow];
                if(panel.tileM.tile[tileNum1].collision || panel.tileM.tile[tileNum2].collision) entity.collisionOn = true;
                break;
            case RIGHT:
                entityRightCol = (entityRightWorldX + entity.speed)/panel.tileSize;
                tileNum1 = panel.tileM.mapTileNum[panel.currentMap.getIndex()][entityRightCol][entityTopRow];
                tileNum2 = panel.tileM.mapTileNum[panel.currentMap.getIndex()][entityRightCol][entityBottomRow];
                if(panel.tileM.tile[tileNum1].collision || panel.tileM.tile[tileNum2].collision) entity.collisionOn = true;
                break;
        }
    }
    public int checkObject(Entity entity, boolean player) {
        int index = 999;
        int c = -1;

        for(Entity obj : panel.obj[panel.currentMap.getIndex()]) {
            c++;
            if (obj != null) {

                entity.solidArea.x += entity.worldX;
                entity.solidArea.y += entity.worldY;

                obj.solidArea.x += obj.worldX;
                obj.solidArea.y += obj.worldY;

                parseSolidArea(entity);

                if (entity.solidArea.intersects(obj.solidArea)) {
                    if (obj.collision) entity.collisionOn = true;
                    if (player) index = c;
                }

                entity.solidArea.x = entity.solidAreaDefaultX;
                entity.solidArea.y = entity.solidAreaDefaultY;
                obj.solidArea.x = obj.solidAreaDefaultX;
                obj.solidArea.y = obj.solidAreaDefaultY;
            }
        }
        return index;
    }

    //NPC OR MONSTER COLLISION
    public int checkEntity(Entity entity, Entity[] target) {
        int index = 999;
        int c = -1;

        for(Entity e : target) {
            c++;
            if (e != null) {

                entity.solidArea.x += entity.worldX;
                entity.solidArea.y += entity.worldY;

                e.solidArea.x += e.worldX;
                e.solidArea.y += e.worldY;

                parseSolidArea(entity);

                if (entity.solidArea.intersects(e.solidArea) && e != entity) {
                    entity.collisionOn = true;
                    index = c;
                }

                entity.solidArea.x = entity.solidAreaDefaultX;
                entity.solidArea.y = entity.solidAreaDefaultY;
                e.solidArea.x = e.solidAreaDefaultX;
                e.solidArea.y = e.solidAreaDefaultY;
            }
        }
        return index;
    }
    public boolean checkPlayer(Entity entity) {
        boolean contactPlayer = false;
        entity.solidArea.x += entity.worldX;
        entity.solidArea.y += entity.worldY;

        panel.player.solidArea.x += panel.player.worldX;
        panel.player.solidArea.y += panel.player.worldY;

        parseSolidArea(entity);

        if (entity.solidArea.intersects(panel.player.solidArea)) {
            entity.collisionOn = true;
            contactPlayer = true;
        }

        entity.solidArea.x = entity.solidAreaDefaultX;
        entity.solidArea.y = entity.solidAreaDefaultY;
        panel.player.solidArea.x = panel.player.solidAreaDefaultX;
        panel.player.solidArea.y = panel.player.solidAreaDefaultY;
        return contactPlayer;
    }

    // UTILITY
    private void parseSolidArea(Entity entity) {
        switch (entity.direction) {
            case UP -> entity.solidArea.y -= entity.speed;
            case DOWN -> entity.solidArea.y += entity.speed;
            case LEFT -> entity.solidArea.x -= entity.speed;
            case RIGHT -> entity.solidArea.x += entity.speed;
        }
    }

}
