package cz.jzitnik.game.entities;

import lombok.Getter;
import lombok.Setter;

import java.lang.reflect.InvocationTargetException;
import java.util.List;

import cz.jzitnik.game.Game;
import cz.jzitnik.game.annotations.ReduceFallDamage;
import cz.jzitnik.game.core.reducefalldamage.Reducer;
import cz.jzitnik.game.core.sound.SoundKey;
import cz.jzitnik.game.ui.Window;
import cz.jzitnik.tui.ScreenRenderer;

@Getter
@Setter
public class Player {
    private int health = 10;
    private int hunger = 10;
    private int fallDistance = 0;
    private Block playerBlock1;
    private Block playerBlock2;
    private boolean burning = false;
    private int burningTimeout;
    private boolean burningState = false;

    public synchronized void heal() {
        if (hunger > 3 && health < 10) {
            health = Math.min(health + 1, 10);
        }
    }

    public synchronized void drainHunger() {
        if (hunger > 0) {
            hunger--;
        }
    }

    public void addFalling() {
        fallDistance++;
    }

    public void resetHealth() {
        health = 10;
    }

    public void resetHunger() {
        hunger = 10;
    }

    public void fell(List<Block> fallblock, Game game, ScreenRenderer screenRenderer) {
        var block = fallblock.stream().filter(b -> b.getClass().isAnnotationPresent(ReduceFallDamage.class))
                .findFirst();
        int damage = Math.max(fallDistance - 3, 0);
        if (block.isPresent()) {
            var reducerClass = block.get().getClass().getAnnotation(ReduceFallDamage.class).value();
            try {
                Reducer reducer = reducerClass.getDeclaredConstructor().newInstance();
                damage = reducer.reduce(damage);
            } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException | NoSuchMethodException | SecurityException e) {
                e.printStackTrace();
                System.exit(0);
            }
        }
        dealDamage(damage, game, screenRenderer);
        fallDistance = 0;
    }

    public synchronized void dealDamage(int amount, Game game, ScreenRenderer screenRenderer) {
        health = Math.max(0, health - amount);
        if (amount != 0) {
            game.playerHit(screenRenderer);
            game.getGameStates().dependencies.sound.playSound(game.getConfiguration(), SoundKey.HURT, null);
        }

        if (health <= 0) {
            game.setWindow(Window.DEATH_SCREEN);
            screenRenderer.render(game);
        }
    }

    public synchronized void dealDamage(Game game, ScreenRenderer screenRenderer) {
        dealDamage(1, game, screenRenderer);
    }
}
