package pathgame.gameplay;

/**
 * A container for all camera specific functions
 *
 * @author julia
 */
public class Camera
{
    private final static int CAM_SPEED = 64;

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

    private float lastCamOffsetX = 0.0f;
    private float lastCamOffsetY = 0.0f;
    private float camOffsetX = 0.0f;
    private float camOffsetY = 0.0f;

    /**
     * Recalculates the camera position every gametick based on user input
     *
     * @param level a level containing the current map and the current player
     * @param gamestate the gamestate
     */
    public void tick(Level level, Gamestate gamestate)
    {
        lastCamOffsetX = camOffsetX;
        lastCamOffsetY = camOffsetY;
        lastScale = scale;

        if(!level.getPlayer().isMoving() && gamestate.is(Gamestates.GAMEPLAY))
        {
            if(Keys.ZOOM_IN_KEY.isDown())
            {
                scale *= 1.1f;
            }
            else if(Keys.ZOOM_OUT_KEY.isDown())
            {
                scale /= 1.1f;
            }

            if(Keys.CAM_UP_KEY.isDown())
            {
                camOffsetY += CAM_SPEED;
            }
            if(Keys.CAM_DOWN_KEY.isDown())
            {
                camOffsetY -= CAM_SPEED;
            }
            if(Keys.CAM_LEFT_KEY.isDown())
            {
                camOffsetX += CAM_SPEED;
            }
            if(Keys.CAM_RIGHT_KEY.isDown())
            {
                camOffsetX -= CAM_SPEED;
            }
        }
    }

    /**
     * Limits scale of camera
     *
     * @param zoomRestriction the lower zoom factor restriction (zooming out
     * restriction)
     * @return a tile texture constructed from a given texture id
     */
    public void limitScale(float zoomRestriction)
    {
        if(scale <= zoomRestriction)
        {
            scale = zoomRestriction;
        }
        if(lastScale <= zoomRestriction)
        {
            lastScale = zoomRestriction;
        }

    }

    /**
     * Resetting the camera to focus the player
     *
     */
    public void reset()
    {
        camOffsetX = 0.0f;
        camOffsetY = 0.0f;
        lastCamOffsetX = 0.0f;
        lastCamOffsetY = 0.0f;
    }

    /**
     * Returns the interpolated scale
     *
     * @param lag the render lag
     * @return the interpolated scale
     */
    public float getInterpolatedScale(float lag)
    {
        return lastScale + (scale - lastScale) * lag;
    }

    /**
     * Returns the x-offset of the camera to the player
     *
     * @param offX the x-offset of the map
     * @param minOffX the minimum x-offset restriction of the camera to prevent
     * going outside the screen
     * @param lag the render lag
     * @param interScale the interpolated scale
     * @return the x-offset of the camera to the player
     */
    public float getCamOffsetX(float offX, float minOffX, float lag, float interScale)
    {
        float interCamX = lastCamOffsetX + (camOffsetX - lastCamOffsetX) * lag;
        if(offX + interCamX > 0.0f)
        {
            camOffsetX = -offX;
            if(lastCamOffsetX > camOffsetX)
            {
                lastCamOffsetX = camOffsetX;
            }
            interCamX = lastCamOffsetX + (camOffsetX - lastCamOffsetX) * lag;
        }
        if(offX + interCamX < minOffX)
        {
            camOffsetX = minOffX - offX;
            if(lastCamOffsetX < camOffsetX)
            {
                lastCamOffsetX = camOffsetX;
            }
            interCamX = lastCamOffsetX + (camOffsetX - lastCamOffsetX) * lag;
        }
        return offX + interCamX;
    }

    /**
     * Returns the y-offset of the camera to the player
     *
     * @param offY the y-offset of the map
     * @param minOffY the minimum y-offset restriction of the camera to prevent
     * going outside the screen
     * @param lag the render lag
     * @param interScale the interpolated scale
     * @return the y-offset of the camera to the player
     */
    public float getCamOffsetY(float offY, float minOffY, float lag, float interScale)
    {
        float interCamY = lastCamOffsetY + (camOffsetY - lastCamOffsetY) * lag;
        if(offY + interCamY > 0.0f)
        {
            camOffsetY = -offY;
            if(lastCamOffsetY > camOffsetY)
            {
                lastCamOffsetY = camOffsetY;
            }
            interCamY = lastCamOffsetY + (camOffsetY - lastCamOffsetY) * lag;
        }
        if(offY + interCamY < minOffY)
        {
            camOffsetY = minOffY - offY;
            if(lastCamOffsetY < camOffsetY)
            {
                lastCamOffsetY = camOffsetY;
            }
            interCamY = lastCamOffsetY + (camOffsetY - lastCamOffsetY) * lag;
        }
        return offY + interCamY;
    }
}
