"""
B-ASIC Signal Flow Graph Module.
TODO: More info.
"""

from b_asic.operation import Operation
from b_asic.basic_operation import BasicOperation
from b_asic.signal import Signal, SignalSource, SignalDestination
from b_asic.simulation import SimulationState, OperationState
from typing import List, Dict, Union
from graph_id import GraphIDGenerator, GraphID


class SFG(BasicOperation):
	"""
	Signal flow graph.
	TODO: More info.
	"""

	_graph_objects: Dict(GraphID, Union(Operation, Signal))
	_graph_id_generator: GraphIDGenerator

	def __init__(self, input_destinations: List[SignalDestination], output_sources: List[SignalSource]):
		"""
		Construct a SFG.
		"""
		super().__init__()
		# TODO: Allocate input/output ports with appropriate IDs.
		
		self._graph_objects = dict # Map Operation ID to Operation objects
		self._graph_id_generator = GraphIDGenerator() 

		# TODO: Traverse the graph between the inputs/outputs and add to self._operations.
		# TODO: Connect ports with signals with appropriate IDs.

	def evaluate(self, inputs: list) -> list:
		return [] # TODO: Implement

	def add_operation(self, operation: Operation) -> GraphID:
		"""
		Adds the entered operation to the SFG's dictionary of graph objects and
	 	returns a generated GraphID for it.
		"""
		return self._add_graph_obj(operation, 'op')


	def add_signal(self, signal: Signal) -> GraphID:
		"""
		Adds the entered signal to the SFG's dictionary of graph objects and returns
		a generated GraphID for it.
		"""
		return self._add_graph_obj(signal, 's')


	def _add_graph_obj(self, obj: Union[Operation, Signal], operation_id_type: str):
		graph_id = self._graph_id_generator.get_next_id(operation_id_type)
		self._graph_objects[graph_id] = obj
		return graph_id