package pathgame.gameplay;

import pathgame.algorithm.TravellingSalesAlg;
import pathgame.logging.Logger;
import pathgame.tilemap.TileMap;
import pathgame.tilemap.TileMapGenerator;

/**
 * A level of the game containing the current map and the current player
 *
 * @author julia
 */
public final class Level
{
    private final Player player = new Player();
    private int level = 1;
    private TileMap map = null;
    private boolean showScoreMenu = false;
    private boolean showAfterScore = false;

    /**
     * Contructor generating and initializing new Level and Player
     */
    public Level()
    {
        reset();
    }

    /**
     * Checks gamestate changes every gametick based on user input and game
     * events
     *
     * @param gamestate the gamestate
     */
    public void tick(Gamestate gamestate)
    {
        map.tick();
        if(gamestate.is(Gamestates.GAMEPLAY) && !showScoreMenu)
        {
            player.tick(map);
        }
        if(gamestate.is(Gamestates.GAMEPLAY) && !showScoreMenu && (player.hasLost() || player.hasWon()))
        {
            showScoreMenu = true;
        }
        else if(showScoreMenu && Keys.CONFIRM_KEY.getTime() == 1)
        {
            showScoreMenu = false;
            showAfterScore = true;
        }
    }

    /**
     * Loads the next level
     */
    public void nextLevel()
    {
        level++;
        reset();
    }

    /**
     * Resets the current level
     */
    public void reset()
    {
        int levelW = Math.round(16.0f + (level * 16.0f / 9.0f));
        int levelH = Math.round(9.0f + (level * 16.0f / 16.0f));
        int towns = Math.round(2.0f + level * 0.5f);

        map = TileMapGenerator.getMap(levelW, levelH, level, towns);
        player.reset(map.getHomeX(), map.getHomeY());
        player.setObjectivesAmount(map.getNumberOfTowns());

        int algoEnergy = TravellingSalesAlg.calcSalesPathLen(map, player);

        player.setEnergySupply(algoEnergy);

        Logger.onLevelReset(level, player, map);
    }

    /**
     * Returns the map of the current level
     *
     * @return the map of the current level
     */
    public TileMap getMap()
    {
        return map;
    }

    /**
     * Returns the player of the current level
     *
     * @return the player of the current level
     */
    public Player getPlayer()
    {
        return player;
    }

    /**
     * Returns the current level
     *
     * @return the current level
     */
    public int getLevel()
    {
        return level;
    }

    /**
     * Returns if the AfterScoreMenu is showed
     *
     * @return if the AfterScoreMenu is showed
     */
    public boolean isShowingAfterScore()
    {
        return showAfterScore;
    }

    /**
     * Sets if the AfterScoreMenu should be showed
     *
     * @param show sets if the AfterScore should be showed
     */
    public void setShowAfterScore(boolean show)
    {
        showAfterScore = show;
    }

    /**
     * Returns if the ScoreMenu is showed
     *
     * @return if the ScoreMenu is showed
     */
    public boolean isShowingScoreMenu()
    {
        return showScoreMenu;
    }
}
