/* ###
 * IP: GHIDRA
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ghidra.graph.viewer.layout;

import java.awt.Shape;
import java.awt.geom.Point2D;

import com.google.common.base.Function;

import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.visualization.renderers.BasicEdgeRenderer;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import ghidra.graph.VisualGraph;
import ghidra.graph.viewer.VisualEdge;
import ghidra.graph.viewer.VisualVertex;
import ghidra.graph.viewer.layout.LayoutListener.ChangeType;
import ghidra.util.task.TaskMonitor;

/**
 * The interface for defining functions provided that are additional to that of {@link Layout}.
 *
 * @param <V> the vertex type
 * @param <E> the edge type
 */
//@formatter:off
public interface VisualGraphLayout<V extends VisualVertex, 
                                   E extends VisualEdge<V>>
                                   

// TODO Note: 'Layout' is a Jung interface.   We can always add a layer of indirection to get
//             away from Jung, as needed.
		extends Layout<V, E> {
//@formatter:on

	/**
	 * Adds a layout listener 
	 * @param listener the listener
	 */
	public void addLayoutListener(LayoutListener<V, E> listener);

	/**
	 * Removes a layout listener
	 * @param listener the listener
	 */
	public void removeLayoutListener(LayoutListener<V, E> listener);

	/**
	 * Returns true if this layout uses articulated edges.  All {@link VisualEdge}s have the
	 * ability to articulate.  This method servers as a shortcut for algorithms so that they 
	 * need not loop over all edges to determine if they have articulations.  (Looping over
	 * large graphs is time intensive.)
	 * 
	 * <P><A HREF="../VisualEdge.html#articulations">What are articulations?</A>
	 * 
	 * @return true if this layout uses articulated edges.
	 */
	public boolean usesEdgeArticulations();

	/**
	 * Signals to again layout the current graph.  The locations generated by the layout will
	 * be returned, but not actually applied to the graph.  This allows clients to generate new
	 * locations and then apply them in a delayed fashion, like for animation.
	 * 
	 * @param graph the graph that contains the vertices to layout 
	 * @param monitor the task monitor used to report progress or to cancel
	 * @return the layout locations
	 */
	public LayoutPositions<V, E> calculateLocations(VisualGraph<V, E> graph, TaskMonitor monitor);

	/**
	 * Creates a new version of this layout using the given graph.  Also, the new layout will
	 * have the same state as this layout (i.e., vertex positions (and edge articulations, 
	 * if applicable)).
	 * 
	 * @param newGraph the new graph for the new layout
	 * @return the new layout
	 */
	public VisualGraphLayout<V, E> cloneLayout(VisualGraph<V, E> newGraph);

	/**
	 * Allows the client to change the location while specifying the type of change
	 * 
	 * @param v the vertex
	 * @param location the new location
	 * @param changeType the type of change
	 */
	public void setLocation(V v, Point2D location, ChangeType changeType);

	/**
	 * Returns the graph of this layout
	 * 
	 * @return the graph of this layout
	 */
	public VisualGraph<V, E> getVisualGraph();

	/**
	 * Returns an optional edge renderer.  This is used to render each edge.
	 * 
	 * @return an optional edge renderer
	 */
	public BasicEdgeRenderer<V, E> getEdgeRenderer();

	/**
	 * Returns an optional edge shape transformer.  This is used to create shapes for each edge.
	 * 
	 * @return an optional edge shape transformer
	 */
	public Function<E, Shape> getEdgeShapeTransformer();

	/**
	 * Returns an optional custom edge label renderer.  This is used to add labels to the edges.
	 * 
	 * @return an optional renderer
	 */
	public Renderer.EdgeLabel<V, E> getEdgeLabelRenderer();

	/**
	 * Cleanup any resource being managed by this layout.
	 */
	public void dispose();

}
