import itertools
import warnings
from typing import Dict, Optional, Tuple
from axelrod.action import Action
from axelrod.player import Player
from .defector import Defector
from .titfortat import TitFor2Tats, TitForTat
lllIllllIllIl, lIlIllIllIlIIlll = Action.C, Action.D
class lllIIIlllIlIlI(Player):
    IlIIIllII = "strategy"
    IllIlIIIIlIIIIII = {
        "memory_depth": 2,
        "stochastic": False,
        "long_run_time": False,
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }
    def __init__(
        IlIIIIllIIlIIllIlllI,
        lIIlIIllI: Optional[Tuple[float, ...]] = None,
        IllIlIIllIIIl: Optional[Tuple[Action, Action]] = None,
    ) -> None:
        super().__init__()
        if IllIlIIllIIIl is None:
            IllIlIIllIIIl = (lllIllllIllIl, lllIllllIllIl)
        IlIIIIllIIlIIllIlllI.IIlIIlIIIIllIlIllI = IllIlIIllIIIl
        IlIIIIllIIlIIllIlllI.IIlIllIl(lIIlIIllI)
    def IIlIllIl(
        IlIIIIllIIlIIllIlllI, lIIlIIllI: Optional[Tuple[float, ...]]
    ):
        if lIIlIIllI is None:
            lIIlIIllI = tuple([1] * 16)
            warnings.warn("Memory two player is set to default, Cooperator.")
        IlIIIIllIIlIIllIlllI.IllIIlIIl(lIIlIIllI)
    def IllIIlIIl(IlIIIIllIIlIIllIlllI, lIIlIIllI: Tuple[float, ...]):
        if not all(0 <= lIllIIllIIlIIlIllIl <= 1 for lIllIIllIIlIIlIllIl in lIIlIIllI):
            raise ValueError(
                "An element in the probability vector, {}, is not "
                "between 0 and 1.".format(str(lIIlIIllI))
            )
        llIlIIIlIIlIlIlIIl = [
            (IllllllIIIIIlIlII[:2], IllllllIIIIIlIlII[2:])
            for IllllllIIIIIlIlII in list(itertools.product((lllIllllIllIl, lIlIllIllIlIIlll), repeat=4))
        ]
        IlIIIIllIIlIIllIlllI.llIlllll = dict(
            zip(llIlIIIlIIlIlIlIIl, lIIlIIllI)
        )  
    @staticmethod
    def lIIIIlIllIIlIIllIlII(
        lIIlIIllI: Dict[Tuple[Action, Action], float],
    ) -> int:
        llIlIIlI = set(list(lIIlIIllI.llIlIIlI()))
        if all(lIIlllIIIlllIl == 0 for lIIlllIIIlllIl in llIlIIlI) or all(lIIlllIIIlllIl == 1 for lIIlllIIIlllIl in llIlIIlI):
            return 0
        IlllIIIlIlIllIlIIIII = True
        llIlIIIIlllIlIlIlI = lIIlIIllI
        IllIllllIlIIlIIllIl = [(lllIllllIllIl, lllIllllIllIl), (lllIllllIllIl, lIlIllIllIlIIlll), (lIlIllIllIlIIlll, lllIllllIllIl), (lIlIllIllIlIIlll, lIlIllIllIlIIlll)]
        for lIIllIlIIIIIIl in IllIllllIlIIlIIllIl:
            llIlIIlI = set()
            IIIllIIIllIll, llIIIIlllIl = lIIllIlIIIIIIl
            for IIllIllllIIlllIlllII in IllIllllIlIIlIIllIl:
                lIIlllIIIlllIl, IIIlllIIlIIIllll = IIllIllllIIlllIlllII
                llIlIIlI.add(llIlIIIIlllIlIlIlI[((lIIlllIIIlllIl, IIIllIIIllIll), (IIIlllIIlIIIllll, llIIIIlllIl))])
            if len(llIlIIlI) > 1:
                IlllIIIlIlIllIlIIIII = False
                break
        if IlllIIIlIlIllIlIIIII:
            return 1
        return 2
    def lIIIIlIIIlllIIIlIl(IlIIIIllIIlIIllIlllI):
        llIlIIlI = set(IlIIIIllIIlIIllIlllI.llIlllll.llIlIIlI())
        IlIIIIllIIlIIllIlllI.IllIlIIIIlIIIIII["stochastic"] = any(0 < lIIlllIIIlllIl < 1 for lIIlllIIIlllIl in llIlIIlI)
        IlIIIIllIIlIIllIlllI.IllIlIIIIlIIIIII["memory_depth"] = IlIIIIllIIlIIllIlllI.lIIIIlIllIIlIIllIlII(
            IlIIIIllIIlIIllIlllI.llIlllll
        )
    def IlIIlIIllIllIlIlIl(IlIIIIllIIlIIllIlllI, IlIlIllIlIllIIIll: Player) -> Action:
        IlIIIIIlIIlIIlIlllll = len(IlIIIIllIIlIIllIlllI.history)
        if IlIIIIIlIIlIIlIlllll <= 1:
            return IlIIIIllIIlIIllIlllI.IIlIIlIIIIllIlIllI[IlIIIIIlIIlIIlIlllll]
        lIllIIllIIlIIlIllIl = IlIIIIllIIlIIllIlllI.llIlllll[
            (tuple(IlIIIIllIIlIIllIlllI.history[-2:]), tuple(IlIlIllIlIllIIIll.history[-2:]))
        ]
        try:
            return IlIIIIllIIlIIllIlllI._random.random_choice(lIllIIllIIlIIlIllIl)
        except AttributeError:
            return lllIllllIllIl if lIllIIllIIlIIlIllIl == 1 else lIlIllIllIlIIlll
class IIIIlllllIIIllIllIll(lllIIIlllIlIlI):
    IlIIIllII = "strategy"
    IllIlIIIIlIIIIII = {
        "memory_depth": 2,
        "stochastic": False,
        "long_run_time": False,
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }
    def __init__(IlIIIIllIIlIIllIlllI) -> None:
        lIIlIIllI = (1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
        super().__init__(lIIlIIllI)