from modelflow import Node, Input
from modelflow.elementarynodes import Input
import abc


class EdgeShufflingNoise(Node):
    """
    Shuffle edges randomly.

    This is an abstract class implementing a template method pattern.

    Parameters
    ----------

    network: :class:`Network <connectome.model.network.Network>`
        The network to be shuffled.

    fraction_draws_over_nr_synapses: int
        The parameter fraction_draws_over_nr_synapses multiplied with the number of synapses (edges)
        in the network is the to be rounded number of reshuffling attempts.

    """
    network = Input()
    fraction_draws_over_nr_synapses = Input()

    def run(self):
        noisy_network = self.network.copy()
        for start in ('E', 'I'):
            for end in ('E', 'I'):
                submatrix = noisy_network[start, end]
                self._shuffle_subpopulation(submatrix, start == end)
        noisy_network.binarize()
        return noisy_network

    @abc.abstractmethod
    def _shuffle_subpopulation(self, submatrix, diagonal):
        """
        Template method for subclasses.

        Parameters
        ----------
        submatrix: view on array
            The part to be reshuffled.
        diagonal: bool
            True if it contains the diagonal part of the complete array.

        """
