package pp.monopoly.client.gui;

import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial.CullHint;
import com.jme3.scene.shape.Quad;

import pp.monopoly.client.MonopolyApp;
import pp.monopoly.model.Board;

/**
 * Represents the visual view of a {@link Board}, used to display the map structure and elements.
 * This class handles the graphical representation of the board, including background setup and grid lines.
 */
class MapView {
    private static final float FIELD_SIZE = 40f;
    private static final float BACKGROUND_DEPTH = -4f;
    private static final ColorRGBA BACKGROUND_COLOR = new ColorRGBA(0, 0.05f, 0.05f, 0.5f);

    private final MonopolyApp app;
    private final Node mapNode = new Node("map");
    private final Board board;
    private final MapViewSynchronizer synchronizer;

    /**
     * Constructs a new MapView for a given {@link Board} and {@link MonopolyApp}.
     *
     * @param board the board to visualize
     * @param app   the main application instance
     */
    MapView(Board board, MonopolyApp app) {
        this.board = board;
        this.app = app;
        this.synchronizer = new MapViewSynchronizer(this);
        setupBackground();
        app.getGameLogic().addListener(synchronizer);
    }

    /**
     * Unregisters the {@link MapViewSynchronizer} from listening to board changes.
     */
    void unregister() {
        app.getGameLogic().removeListener(synchronizer);
    }

    /**
     * Sets up the background of the map view using a quad geometry.
     */
    private void setupBackground() {
        Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", BACKGROUND_COLOR);
        mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
        Geometry background = new Geometry("MapBackground", new Quad(board.getWidth() * FIELD_SIZE, board.getHeight() * FIELD_SIZE));
        background.setMaterial(mat);
        background.setLocalTranslation(0f, 0f, BACKGROUND_DEPTH);
        background.setCullHint(CullHint.Never);
        mapNode.attachChild(background);
    }

    /**
     * Gets the root node containing all visual elements in this map view.
     *
     * @return the root node for the map view
     */
    public Node getNode() {
        return mapNode;
    }

    public Board getBoard() {
        return board;
    }
}
