package carcassonne.view.main;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.stream.Stream;

import javax.swing.JLayeredPane;
import javax.swing.JScrollPane;
import javax.swing.OverlayLayout;

/**
 * {@link JScrollPane} that depicts the layers of a {@link JLayeredPane}. It is just a scroll pane that manages its own
 * layered pane.
 * @author Timur Saglam
 */
public class LayeredScrollPane extends JScrollPane {

    private static final long serialVersionUID = 7863596860273426396L;
    private static final int SCROLL_SPEED = 15;
    private final JLayeredPane layeredPane;

    /**
     * Creates a layered scroll pane and centers it for a certain grid size.
     */
    public LayeredScrollPane() {
        layeredPane = new JLayeredPane();
        layeredPane.setLayout(new OverlayLayout(layeredPane));
        setViewportView(layeredPane);
        getVerticalScrollBar().setUnitIncrement(SCROLL_SPEED);
        getHorizontalScrollBar().setUnitIncrement(SCROLL_SPEED);
    }

    /**
     * Adds any number of components as layers in the given order.
     * @param components the components to add as layers.
     */
    public void addLayers(Component... components) {
        for (int i = 0; i < components.length; i++) {
            layeredPane.add(components[i], i);
        }
    }

    /**
     * Removes any number of layers if they are part of this scroll pane.
     * @param components are the components and therefore layers to remove.
     */
    public void removeLayers(Component... components) {
        Stream.of(components).forEach(layeredPane::remove);
    }

    /**
     * Repaint the layered pane and its layers.
     */
    public void repaintLayers() {
        layeredPane.repaint();
    }

    /**
     * Centers the scroll pane view to show the center of the grid. Make sure to call revalidate on the UI root before
     * calling this method to avoid incorrect centering.
     * @param gridWidth is the current grid with in tiles.
     * @param gridHeight is the current height with in tiles.
     * @param zoomLevel is the current zoom level and therefore also the tile size.
     */
    public void centerScrollPaneView(int gridWidth, int gridHeight, int zoomLevel) {
        Dimension size = new Dimension(gridWidth * zoomLevel, gridHeight * zoomLevel);
        Rectangle bounds = getViewport().getViewRect();
        int x = (int) (Math.round((size.width - bounds.width) / 2.0));
        int y = (int) (Math.round((size.height - bounds.height) / 2.0));
        getViewport().setViewPosition(new Point(x, y));
    }
}