import json

from .topology import Topology as Topo
from .node import QKDNode
from ..kernel.timeline import Timeline


class QKDTopo(Topo):
    """Class for generating QKD network

    Class QKDTopo is the child of class Topology. QKD nodes, quantum channels,
    classical channels and timeline for simulation could be generated by using
    this class.

    Attributes:
        nodes (Dict[str, List[Node]]): mapping of type of node to a list of same type node.
        qchannels (List[QuantumChannel]): list of quantum channel objects in network.
        cchannels (List[ClassicalChannel]): list of classical channel objects in network.
        tl (Timeline): the timeline used for simulation
    """
    QKD_NODE = "QKDNode"

    def _load(self, filename):
        topo_config = json.load(open(filename))

        self._get_templates(topo_config)
        self._add_timeline(topo_config)
        self._add_nodes(topo_config)
        self._add_qchannels(topo_config)
        self._add_cchannels(topo_config)
        self._add_cconnections(topo_config)

    def _add_timeline(self, config):
        stop_time = config.get(Topo.STOP_TIME, float('inf'))
        self.tl = Timeline(stop_time)

    def _add_nodes(self, config):
        for node in config[Topo.ALL_NODE]:
            # TODO: add encoding configuration for QKD nodes
            seed = node[Topo.SEED]
            node_type = node[Topo.TYPE]
            name = node[Topo.NAME]
            template_name = node.get(Topo.TEMPLATE, None)
            template = self.templates.get(template_name, {})

            if node_type == self.QKD_NODE:
                node = QKDNode(name, self.tl,
                               seed=seed, component_templates=template)
            else:
                raise NotImplementedError("Unknown type of node")

            if node_type in self.nodes:
                self.nodes[node_type].append(node)
            else:
                self.nodes[node_type] = [node]
