import math

from axelrod.action import Action
from axelrod.player import Player

C, D = Action.C, Action.D


class CotoDeRatio(Player):
    """The player will always aim to bring the ratio of co-operations to
    defections closer to the ratio as given in a sub class

    Names:

    - Co to Do Ratio: Original Name by Timothy Standen
    """

    classifier = {
        "stochastic": False,
        "memory_depth": float("inf"),  # Long memory
        "makes_use_of": set(),
        "long_run_time": False,
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }

    def strategy(self, opponent: Player) -> Action:
        # Initially cooperate
        if len(opponent.history) == 0:
            return C
        # Avoid initial division by zero
        if not opponent.defections:
            return D
        # Otherwise compare ratio to golden mean
        cooperations = opponent.cooperations + self.cooperations
        defections = opponent.defections + self.defections
        if cooperations / defections > self.ratio:
            return D
        return C


class Golden(CotoDeRatio):
    """The player will always aim to bring the ratio of co-operations to
    defections closer to the golden mean

    Names:

    - Golden: Original Name by Timothy Standen
    """

    name = "$\phi$"
    ratio = (1 + math.sqrt(5)) / 2


class Pi(CotoDeRatio):
    """The player will always aim to bring the ratio of co-operations to
    defections closer to the pi

    Names:

    - Pi: Original Name by Timothy Standen
    """

    name = "$\pi$"
    ratio = math.pi


class e(CotoDeRatio):
    """The player will always aim to bring the ratio of co-operations to
    defections closer to the e

    Names:

    - e: Original Name by Timothy Standen
    """

    name = "$e$"
    ratio = math.e
