package pp.monopoly.client.gui;

import com.jme3.scene.Node;
import com.jme3.scene.Spatial;

import pp.monopoly.model.Board;
import pp.monopoly.model.Item;
import pp.monopoly.model.Visitor;
import pp.monopoly.notification.GameEventListener;
import pp.monopoly.notification.ItemAddedEvent;
import pp.monopoly.notification.ItemRemovedEvent;
import pp.view.ModelViewSynchronizer;

/**
 * Abstract base class for synchronizing the visual representation of a {@link Board} with its model state.
 * This class handles the addition and removal of items from the map, ensuring that changes in the model
 * are accurately reflected in the view.
 */
abstract class BoardSynchronizer extends ModelViewSynchronizer<Item> implements Visitor<Spatial>, GameEventListener {
    private final Board board;

    /**
     * Constructs a new BoardSynchronizer.
     *
     * @param board the game board to synchronize
     * @param root  the root node to which the view representations of the board items are attached
     */
    protected BoardSynchronizer(Board board, Node root) {
        super(root);
        this.board = board;
    }

    /**
     * Translates a model item into its corresponding visual representation.
     *
     * @param item the item from the model to be translated
     * @return the visual representation of the item as a {@link Spatial}
     */
    @Override
    protected Spatial translate(Item item) {
        return item.accept(this);
    }

    /**
     * Adds the existing items from the board to the view during initialization.
     */
    protected void addExisting() {
        board.getItems().forEach(this::add);
    }

    /**
     * Handles the event when an item is removed from the board.
     *
     * @param event the event indicating that an item has been removed from the board
     */
    @Override
    public void receivedEvent(ItemRemovedEvent event) {
        if (board == event.getBoard()) {
            delete(event.getItem());
        }
    }

    /**
     * Handles the event when an item is added to the board.
     *
     * @param event the event indicating that an item has been added to the board
     */
    @Override
    public void receivedEvent(ItemAddedEvent event) {
        if (board == event.getBoard()) {
            add(event.getItem());
        }
    }
}
