from typing import Tuple, Callable, List, Dict

from tunepy2 import Genome
from tunepy2.interfaces import AbstractGenomeFactory, AbstractRandomNumberGenerator


class RandomGenomeFactory(AbstractGenomeFactory):
    def __init__(
            self,
            dimensions: Tuple,
            rng: AbstractRandomNumberGenerator,
            fitness_func: Callable[..., float],
            *args,
            **kwargs):
        """
        Creates a new RandomGenomeFactory

        :param dimensions: dimensions of bitstrings of Genome objects generated by the factory
        :param rng: random number generator
        :param fitness_func: fitness function passed into new Genome objects that accepts a bitstring
        :param args: will be passed into fitness_func
        :param kwargs: will be passed into fitness_func
        """
        self._rng = rng
        self._dimensions = dimensions
        self._fitness_func = fitness_func
        self._args = args
        self._kwargs = kwargs

    def build(self, prior_genomes: List[Genome]) -> Genome:
        """ Builds a new Genome from a list of priors

        :param prior_genomes: list of prior Genomes
        :return: a new Genome object
        """
        bitstring = self._rng.random_int_array(0, 1, self._dimensions)
        return Genome(self._fitness_func, bitstring, *self._args, **self._kwargs)

    @property
    def dimensions(self) -> Tuple:
        """

        :return: the dimensions of Genome objects returned by this factory
        """
        return self._dimensions
