package pathgame;

import me.hammerle.snuviengine.api.IGame;
import me.hammerle.snuviengine.api.Renderer;
import pathgame.algorithm.TravellingSalesAlg;
import pathgame.gameplay.Gamestate;
import pathgame.gameplay.Gamestates;
import pathgame.gameplay.Keys;
import pathgame.rendering.TileMapRenderer;
import pathgame.tilemap.TileMap;
import pathgame.tilemap.TileMapGenerator;
import pathgame.gameplay.Player;
import pathgame.gameplay.PlayerAbilities;
import pathgame.gameplay.menu.Menu;
import pathgame.rendering.HUDRenderer;
import pathgame.rendering.MenuRenderer;
import pathgame.rendering.PlayerRenderer;
import pathgame.rendering.TileRenderer;

public class PathGame implements IGame
{
    private final Gamestate gamestate = new Gamestate();

    private final TileMapRenderer mapRenderer = new TileMapRenderer();
    private TileMap map = TileMapGenerator.getMap(50, 50, 15);

    private final PlayerRenderer playerRenderer = new PlayerRenderer();
    private final Player player = new Player(1000, 10, PlayerAbilities.NORMAL);

    private final Menu menu = new Menu();
    private final MenuRenderer menuRenderer = new MenuRenderer();
    private final HUDRenderer hudRenderer = new HUDRenderer();

    private float lastScale = 1.0f;
    private float scale = 1.0f;

    public PathGame()
    {
    }

    @Override
    public void tick()
    {
        map.tick();
        mapRenderer.tick();
        if(gamestate.getState() == Gamestates.GAMEPLAY)
        {
            player.tick(map);
        }
        menu.tick(gamestate);

        lastScale = scale;
        if(Keys.ZOOM_IN_KEY.isDown())
        {
            scale *= 1.1f;
        }
        else if(Keys.ZOOM_OUT_KEY.isDown())
        {
            scale /= 1.1f;
        }
        
        if(Keys.TEST_KEY.getTime() == 1)
        {
            map = TileMapGenerator.getMap(50, 50, 15);
            System.out.println(map.getNumberOfTowns());
            TravellingSalesAlg.calcSalesPathLen(map);
        }
    }

    @Override
    public void renderTick(Renderer r, float lag)
    {
        float interScale = lastScale + (scale - lastScale) * lag;
        mapRenderer.setScale(interScale);

        float offX = getMapOffsetX(r, lag, interScale);
        float offY = getMapOffsetY(r, lag, interScale);

        mapRenderer.renderTick(map, r, false, offX, offY);
        switch(gamestate.getState())
        {
            case GAMEPLAY:
                playerRenderer.renderTick(map, mapRenderer, r, player, lag, offX, offY);
                hudRenderer.renderTick(r, player, lag);
                break;
            case MENU:
                menuRenderer.renderTick(r, lag, menu);
                break;

        }
    }

    private float getMapOffsetX(Renderer r, float lag, float interScale)
    {
        float ix = (player.getLastX() + (player.getX() - player.getLastX()) * lag) * interScale * TileRenderer.TILE_SIZE;
        float offX = (-ix + r.getViewWidth() * 0.5f) - TileRenderer.TILE_SIZE * 0.5f * interScale;

        if(offX < -mapRenderer.getWidth(map) + r.getViewWidth())
        {
            return -mapRenderer.getWidth(map) + r.getViewWidth();
        }
        else if(offX > 0.0f)
        {
            return 0.0f;
        }
        return offX;
    }

    private float getMapOffsetY(Renderer r, float lag, float interScale)
    {
        float iy = (player.getLastY() + (player.getY() - player.getLastY()) * lag) * interScale * TileRenderer.TILE_SIZE;
        float offY = (-iy + r.getViewHeight() * 0.5f) - TileRenderer.TILE_SIZE * 0.5f * interScale;

        if(offY < -mapRenderer.getHeight(map) + r.getViewHeight())
        {
            return -mapRenderer.getHeight(map) + r.getViewHeight();
        }
        else if(offY > 0.0f)
        {
            return 0.0f;
        }
        return offY;
    }

    @Override
    public void onStop()
    {
    }
}