package de.samdev.colorrunner.screens.menu;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.math.Vector3;

import java.util.ArrayList;
import java.util.List;

import de.samdev.colorrunner.CRGame;
import de.samdev.colorrunner.input.CRGameInputProcessor;

public abstract class BaseMenu implements Screen {

    private final int VIRTUAL_VIEWPORT_WIDTH = 1024;
    private final int VIRTUAL_VIEWPORT_HEIGHT = 640;

    private List<BaseMenuElement> elements = new ArrayList<BaseMenuElement>();
    private OrthographicCamera cam;
    private SpriteBatch sbatch = new SpriteBatch();
    private ShapeRenderer linebatch = new ShapeRenderer();

    private CRMenuInputProcessor input = new CRMenuInputProcessor(this);

    public BaseMenu() {
        super();

        cam = new OrthographicCamera();

        updateCam();
        init();
    }

    protected abstract void init();

    protected void add(BaseMenuElement e) {
        elements.add(e);
    }

    protected abstract Color getClearColor();

    @Override
    public void show() {
        Gdx.input.setInputProcessor(new InputMultiplexer(input, new GestureDetector(input)));
    }

    @Override
    public void render(float delta) {

        // ####### UPDATE #########

        var cc = getClearColor();
        if (cc != null) Gdx.gl.glClearColor(cc.r, cc.g,  cc.b, 1f);

        for (BaseMenuElement e : elements) {
            e.update(delta);
        }

        // ####### DEBUG RENDER #########

        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        if (CRGame.DEBUG) {

            linebatch.begin(ShapeRenderer.ShapeType.Line);
            linebatch.setColor(0, 0, 1, 1);

            linebatch.rect(0, 0, VIRTUAL_VIEWPORT_WIDTH, VIRTUAL_VIEWPORT_HEIGHT);

            linebatch.end();

        }

        // ####### REAL RENDER #########

        sbatch.begin();
        for (BaseMenuElement e : elements) {
            e.render(sbatch);
        }
        sbatch.end();


    }

    private void updateCam() {

        float deviceW = Gdx.graphics.getWidth();
        float deviceH = Gdx.graphics.getHeight();

        float real_ratio = deviceW / deviceH;
        float virt_ratio = VIRTUAL_VIEWPORT_WIDTH * 1f / VIRTUAL_VIEWPORT_HEIGHT;

        if (real_ratio > virt_ratio) {

            // fix to height

            cam.viewportHeight = VIRTUAL_VIEWPORT_HEIGHT;
            cam.viewportWidth = real_ratio * VIRTUAL_VIEWPORT_HEIGHT;

        } else {

            // fix to width

            cam.viewportHeight = VIRTUAL_VIEWPORT_WIDTH / real_ratio;
            cam.viewportWidth = VIRTUAL_VIEWPORT_WIDTH;

        }

        cam.position.x = VIRTUAL_VIEWPORT_WIDTH  / 2f;
        cam.position.y = VIRTUAL_VIEWPORT_HEIGHT / 2f;

        cam.update();

        sbatch.setProjectionMatrix(cam.combined);
        linebatch.setProjectionMatrix(cam.combined);
    }

    @Override
    public void resize(int width, int height) {

        updateCam();

    }

    @Override
    public void pause() {
        // NOP
    }

    @Override
    public void resume() {
        // NOP
    }

    @Override
    public void hide() {
        // NOP
    }

    @Override
    public void dispose() {

    }

    public void touchDown(int screenX, int screenY) {

        var up = cam.unproject(new Vector3(screenX, screenY, 0));

        var x = up.x;
        var y = up.y;

        for (BaseMenuElement e: elements) {
            if (e.getBounds().contains(x, y)) {
                e.clickTest(x, y);
            }
        }
    }
}
