package fr.uge.graph;

/// An interface representing a weighted graph data structure.
/// This interface defines the core operations for managing nodes and edges
/// in a graph where nodes are predefined and edges have associated weights of type E.
///
/// @param <E> the type of edge weights
public interface Graph<E> {

  /// Returns the total number of nodes in the graph.
  ///
  /// @return the number of nodes in this graph
  int nodeCount();

  /// Retrieves the weight of the edge between two nodes.
  ///
  /// @param src the source node index
  /// @param dst the destination node index
  /// @return the weight of the edge from src to dst, or the default value if no edge exists
  /// @throws IllegalArgumentException if src or dst is negative
  E getWeight(int src, int dst);

  /// Adds an edge with the specified weight between two nodes.
  /// If an edge already exists between the nodes, its weight is updated.
  ///
  /// @param src the source node index
  /// @param dst the destination node index
  /// @param weight the weight to assign to the edge
  /// @throws IllegalArgumentException if src or dst is negative or if the weight is the default value
  void addEdge(int src, int dst, E weight);

  /// Returns an iterable of all edges originating from the specified node.
  ///
  /// @param src the source node index
  /// @return an Iterable of Edge objects representing all outgoing edges from the source node
  /// @throws IllegalArgumentException if src is negative
  Iterable<Edge<E>> edges(int src);

  /// Returns a stream of all edges originating from the specified node.
  ///
  /// @param src the source node index
  /// @return a Stream of Edge objects representing all outgoing edges from the source node
  /// @throws IllegalArgumentException if src is negative
  Stream<Edge<E>> edgeStream(int src);
}