# Path: lcs/strategies/action_selection/BestAction.py
# class BestAction:
# 
#     def __init__(self, all_actions: int):
#         self.all_actions = all_actions
# 
#     def __call__(self, population):
#         cl = population.get_best_classifier()
# 
#         if cl is not None:
#             return cl.action
#         else:
#             return np.random.randint(self.all_actions)
# 
# Path: lcs/strategies/action_selection/RandomAction.py
# class RandomAction:
# 
#     def __init__(self, all_actions: int):
#         self.all_actions = all_actions
# 
#     def __call__(self, population):
#         return np.random.randint(self.all_actions)


from itertools import groupby
from . import RandomAction, BestAction
import numpy as np
import lcs.agents.acs as acs
import lcs.agents.acs2 as acs2



class ActionDelay:
    """
    Action-delay bias.
    Chooses action that was executed a longest time ago.
    """

    def __init__(self, all_actions: int, **kwargs):
        self.all_actions = all_actions
        self.epsilon = kwargs['epsilon']
        self.biased_exploration_prob = kwargs['biased_exploration_prob']
        assert 0 <= self.epsilon <= 1
        assert 0 <= self.biased_exploration_prob <= 1

    def __call__(self, population) -> int:
        if np.random.uniform() < self.epsilon:
            if np.random.uniform() < self.biased_exploration_prob:
                # We are in biased exploration
                if type(population) is acs.ClassifiersList:
                    raise NotImplementedError()
                elif type(population) is acs2.ClassifiersList:
                    return self._handle_latest_action_for_acs2(population)
                else:
                    raise TypeError()
            else:
                # Normal exploration
                return RandomAction(all_actions=self.all_actions)(population)
        else:

# Path: lcs/strategies/action_selection/BestAction.py
# class BestAction:
# 
#     def __init__(self, all_actions: int):
#         self.all_actions = all_actions
# 
#     def __call__(self, population):
#         cl = population.get_best_classifier()
# 
#         if cl is not None:
#             return cl.action
#         else:
#             return np.random.randint(self.all_actions)
# 
# Path: lcs/strategies/action_selection/RandomAction.py
# class RandomAction:
# 
#     def __init__(self, all_actions: int):
#         self.all_actions = all_actions
# 
#     def __call__(self, population):
#         return np.random.randint(self.all_actions)


# Path: lcs/strategies/action_selection/ActionDelay.py
from itertools import groupby
from . import RandomAction, BestAction
import numpy as np
import lcs.agents.acs as acs
import lcs.agents.acs2 as acs2




class ActionDelay:
    """
    Action-delay bias.
    Chooses action that was executed a longest time ago.
    """

    def __init__(self, all_actions: int, **kwargs):
        self.all_actions = all_actions
        self.epsilon = kwargs['epsilon']
        self.biased_exploration_prob = kwargs['biased_exploration_prob']
        assert 0 <= self.epsilon <= 1
        assert 0 <= self.biased_exploration_prob <= 1

    def __call__(self, population) -> int:
        if np.random.uniform() < self.epsilon:
            if np.random.uniform() < self.biased_exploration_prob:
                # We are in biased exploration
                if type(population) is acs.ClassifiersList:
                    raise NotImplementedError()
                elif type(population) is acs2.ClassifiersList:
                    return self._handle_latest_action_for_acs2(population)
                else:
                    raise TypeError()
            else:
                # Normal exploration
                return RandomAction(all_actions=self.all_actions)(population)
        else:

            return BestAction(all_actions=self.all_actions)(population)