"""
Strategies from Axelrod's second tournament. All strategies in this module are
prefixed by `SecondBy` to indicate that they were submitted in Axelrod's Second
tournament by the given author.
"""

from typing import List

import numpy as np

from axelrod.action import Action

from axelrod.interaction_utils import compute_final_score

from axelrod.player import Player

from axelrod.strategies.finite_state_machines import FSMPlayer

C, D = Action.C, Action.D

class SecondByGraaskampKatzen(Player):
    """
    Strategy submitted to Axelrod's second tournament by Jim Graaskamp and Ken
    Katzen (K60R), and came in sixth in that tournament.

    Play Tit-for-Tat at first, and track own score.  At select checkpoints,
    check for a high score.  Switch to Default Mode if:

    - On move 11, score < 23
    - On move 21, score < 53
    - On move 31, score < 83
    - On move 41, score < 113
    - On move 51, score < 143
    - On move 101, score < 293

    Once in Defect Mode, defect forever.

    Names:

    - GraaskampKatzen: [Axelrod1980b]_
    """

    name = "Second by GraaskampKatzen"
    classifier = {
        "memory_depth": float("inf"),
        "stochastic": False,
        "long_run_time": False,
        "inspects_source": False,
        "manipulates_source": False,
        "manipulates_state": False,
    }

    def __init__(self):
        super().__init__()
        self.own_score = 0
        self.mode = "Normal"

    def update_score(self, opponent: Player):
        game = self.match_attributes["game"]
        last_round = (self.history[-1], opponent.history[-1])
        self.own_score += game.score(last_round)[0]

    def strategy(self, opponent: Player) -> Action:
        """Actual strategy definition that determines player's action."""
        if self.mode == "Defect":
            return D

        turn = len(self.history) + 1
        if turn == 1:
            return C

        self.update_score(opponent)

        if (
            turn == 11
            and self.own_score < 23
            or turn == 21
            and self.own_score < 53
            or turn == 31
            and self.own_score < 83
            or turn == 41
            and self.own_score < 113
            or turn == 51
            and self.own_score < 143
            or turn == 101
            and self.own_score < 293
        ):
            self.mode = "Defect"
            return D

        return opponent.history[-1]