package wtf.beatrice.retrorender.engine.ui;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import wtf.beatrice.retrorender.engine.render.DayNightCycle;

public class DebugHud {

    private final SpriteBatch batch;
    private final BitmapFont font;
    private DayNightCycle dayNightCycle;
    private final Texture pixel;

    public DebugHud(DayNightCycle dayNightCycle) {
        this.dayNightCycle = dayNightCycle;

        batch = new SpriteBatch();

        FreeTypeFontGenerator generator =
            new FreeTypeFontGenerator(Gdx.files.internal("fonts/red-hat-mono.ttf"));
        FreeTypeFontGenerator.FreeTypeFontParameter param =
            new FreeTypeFontGenerator.FreeTypeFontParameter();

        param.size = 10; // size in defined scaled framebuffer
        param.color = Color.WHITE;

        // reduce aliasing and smoothing
        param.mono = true; // 1-bit glyphs, no grayscale AA
        param.hinting = FreeTypeFontGenerator.Hinting.None; // no font hinting
        param.borderWidth = 0.2f;
        param.borderColor = Color.WHITE;
        param.shadowOffsetX = 0;
        param.shadowOffsetY = 0;

        // sample font texture as pixels
        param.minFilter = Texture.TextureFilter.Nearest;
        param.magFilter = Texture.TextureFilter.Nearest;

        font = generator.generateFont(param);
        generator.dispose();

        // 1x1 pixel
        Pixmap pm = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
        pm.setColor(1f, 1f, 1f, 1f);
        pm.fill();
        pixel = new Texture(pm);
        pm.dispose();
    }

    // render HUD in virtual resolution
    public void render(int width, int height,
                       PerspectiveCamera camera,
                       float yaw, float pitch) {
        // set up orthographic projection matching target size
        batch.getProjectionMatrix().setToOrtho2D(0, 0, width, height);

        batch.begin();

        if (camera != null) {
            float x = camera.position.x;
            float y = camera.position.y;
            float z = camera.position.z;

            float panelW = 275f;
            float panelH = 45f;
            float panelX = 2f;
            float panelY = height - panelH - 2f;

            // background
            batch.setColor(0f, 0f, 0f, 0.10f);
            batch.draw(pixel, panelX, panelY, panelW, panelH);

            String fpsText = Gdx.graphics.getFramesPerSecond() + " FPS";
            font.draw(batch, fpsText, 5f, height - 5f);

            String posText = String.format("X: %.3f  Y: %.3f  Z: %.3f", x, y, z);
            font.draw(batch, posText, 5f, height - 15f);

            String angText = String.format("Yaw: %.2f  Pitch: %.2f", yaw, pitch);
            font.draw(batch, angText, 5f, height - 25f);

            String dayText = String.format("Time of day: %.3f [%s] Sun height: %.3f", dayNightCycle.getTimeOfDay(), formatTimeOfDay(dayNightCycle.getTimeOfDay()), dayNightCycle.getSunAltitude());
            font.draw(batch, dayText, 5f, height - 35f);
        }

        batch.end();
    }

    private String formatTimeOfDay(float timeOfDay) {
        // keep it in [0,1)
        float t = timeOfDay - (float)Math.floor(timeOfDay);

        float hoursF = t * 24f;
        int hours = (int)Math.floor(hoursF);
        float minutesF = (hoursF - hours) * 60f;
        int minutes = (int)Math.floor(minutesF);

        // clamp just in case of float weirdness
        if (hours < 0)   hours = 0;
        if (hours > 23)  hours = 23;
        if (minutes < 0) minutes = 0;
        if (minutes > 59) minutes = 59;

        return String.format("%02d:%02d", hours, minutes);
    }

    public void dispose() {
        batch.dispose();
        font.dispose();
    }
}
