from __future__ import annotations

from typing import TYPE_CHECKING, Literal

from negmas.sao.components.concession import KindConcessionRecommender

from ..components import TFTAcceptanceStrategy, TFTOfferingStrategy, ZeroSumModel
from .modular import MAPNegotiator

if TYPE_CHECKING:
    pass


__all__ = [
    "NaiveTitForTatNegotiator",
    "SimpleTitForTatNegotiator",
]


class NaiveTitForTatNegotiator(MAPNegotiator):
    """
    Implements a naive tit-for-tat strategy that does not depend on the availability of an opponent model.

    Args:
        name: Negotiator name
        preferences: negotiator preferences
        ufun: negotiator ufun (overrides preferences)
        parent: A controller
        kindness: How 'kind' is the agent. A value of zero is standard tit-for-tat. Positive values makes the negotiator
                  concede faster and negative values slower.
        stochastic: If `True`, the offers will be randomized above the level determined by the current concession
                        which in turn reflects the opponent's concession.
        punish: If `True` the agent punish a partner who does not seem to conede by requiring higher utilities
        initial_concession: How much should the agent concede in the beginning in terms of utility. Should be a number
                            or the special string value 'min' for minimum concession

    Remarks:
        - This negotiator does not keep an opponent model. It thinks only in terms of changes in its own utility.
          If the opponent's last offer was better for the negotiator compared with the one before it, it considers
          that the opponent has conceded by the difference. This means that it implicitly assumes a zero-sum
          situation.
    """

    def __init__(
        self,
        *args,
        kindness=0.0,
        punish=False,
        initial_concession: float | Literal["min"] = "min",
        rank_only: bool = False,
        stochastic: bool = False,
        **kwargs,
    ):
        partner_model = ZeroSumModel(rank_only=rank_only, above_reserve=False)
        if isinstance(initial_concession, str):
            initial_concession = 0
        recommender = KindConcessionRecommender(
            initial_concession=initial_concession, kindness=kindness, punish=punish
        )
        acceptance = TFTAcceptanceStrategy(
            recommender=recommender, partner_ufun=partner_model
        )
        offering = TFTOfferingStrategy(
            recommender=recommender, partner_ufun=partner_model, stochastic=stochastic
        )
        super().__init__(
            *args,
            models=[partner_model, recommender],
            model_names=["partner-model", "concession-recommender"],
            acceptance=acceptance,
            offering=offering,
            **kwargs,
        )


SimpleTitForTatNegotiator = NaiveTitForTatNegotiator
"""A simple tit-for-tat negotiator based on the MAP architecture"""
