"""Genius negotiator implementations - ANAC 2015 agents."""

from __future__ import annotations

from ..negotiator import GeniusNegotiator

__all__ = [
    "AgentBuyog",
    "AgentH",
    "AgentHP",
    "AgentNeo",
    "AgentW",
    "AgentX",
    "AresParty",
    "Atlas3",
    "CUHKAgent2015",
    "DrageKnight",
    "Group2",
    "JonnyBlack",
    "Kawaii",
    "MeanBot",
    "Mercury",
    "PNegotiator",
    "ParsAgent",
    "PhoenixParty",
    "PokerFace",
    "RandomDance",
    "SENGOKU",
    "TUDMixedStrategyAgent",
    "XianFaAgent",
    "Y2015Group2",
]


class AgentBuyog(GeniusNegotiator):
    """
    AgentBuyog negotiation agent.

    **ANAC 2015 Individual Utility Category Runner-up**.

    AgentBuyog estimates the opponent's concession function using regression
    analysis and uses this to determine optimal acceptance thresholds. It
    also estimates opponent preferences to find bids near the Kalai point
    (social welfare maximum).

    **Offering Strategy:**
        Selects bids based on domain competitiveness and opponent difficulty:

        1. Calculates acceptance threshold based on estimated opponent
           difficulty and time-based concession:

           threshold = minPoint + (1 - minPoint) * (1 - t^1.8)

        2. Searches for bids at or above threshold that are closest to
           the estimated Kalai point (maximizing social welfare)
        3. If common bids exist (offered by multiple opponents), prefers
           those with highest utility

        Near deadline (remaining rounds <= 3), threshold is halved.

    **Acceptance Strategy:**
        Multi-criteria acceptance based on:

        - Most recent offer utility vs. threshold
        - Best agreeable bid utility (common to both opponents)
        - Generated bid utility

        Accepts if opponent's offer exceeds all other options and the
        acceptance threshold, especially when near deadline.

    **Opponent Modeling:**
        Sophisticated multi-component model:

        - **Concession estimation**: Uses weighted regression to fit
          exponential concession function exp(alpha) * t^beta to opponent
          bid utilities over time
        - **Leniency calculation**: Derived from slope of estimated
          concession curve, adjusted by a leniency factor
        - **Preference estimation**: Frequency-based issue weight and
          value estimation, normalized after each update
        - **Kalai point estimation**: Finds social welfare maximum
          using estimated opponent preferences
        - **Agent difficulty**: Combined metric of leniency and domain
          competitiveness to assess how hard to negotiate with

    References:
        Fujita, K., Aydogan, R., Baarslag, T., Hindriks, K., Ito, T., &
        Jonker, C. (2017). The Sixth Automated Negotiating Agents Competition
        (ANAC 2015). In Fujita, K., et al. Modern Approaches to Agent-based
        Complex Automated Negotiation. Studies in Computational Intelligence,
        vol 674. Springer, Cham.
    """

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.agentBuyogV2.AgentBuyogMain"
        super().__init__(**kwargs)


class AgentH(GeniusNegotiator):
    """AgentH implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.agenth.AgentH"
        super().__init__(**kwargs)


class AgentHP(GeniusNegotiator):
    """AgentHP implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.AgentHP.AgentHP"
        super().__init__(**kwargs)


class AgentNeo(GeniusNegotiator):
    """AgentNeo implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.AgentNeo.Groupn"
        super().__init__(**kwargs)


class AgentW(GeniusNegotiator):
    """AgentW implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.AgentW.AgentW"
        super().__init__(**kwargs)


class AgentX(GeniusNegotiator):
    """AgentX implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.AgentX.AgentX"
        super().__init__(**kwargs)


class AresParty(GeniusNegotiator):
    """AresParty implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.AresParty.AresParty"
        super().__init__(**kwargs)


class Atlas3(GeniusNegotiator):
    """
    Atlas3 negotiation agent.

    **ANAC 2015 Winner** (Individual Utility & Nash Product categories).

    Atlas3 is a sophisticated negotiation agent developed by Akiyuki Mori that
    uses adaptive strategies based on opponent behavior analysis and game-theoretic
    concepts.

    **Offering Strategy:**
        - Uses appropriate bid searching based on relative utility for linear
          utility spaces
        - Applies replacement method based on frequency analysis of opponent's
          bidding history
        - Concession function derived from Evolutionary Stable Strategy (ESS)
          expected utility analysis
        - Near deadline: cycles through promising bids from opponent's history

    **Acceptance Strategy:**
        - Accepts if the offer utility exceeds the current threshold calculated
          from ESS-based concession function
        - Near deadline: accepts bids above reservation value from candidate list

    **Opponent Modeling:**
        Frequency-based model that tracks opponent's bidding patterns to:
        - Estimate opponent preferences
        - Identify promising bids that might be acceptable to both parties
        - Guide bid search towards mutually beneficial outcomes

    References:
        Mori, A., Ito, T. (2017). Atlas3: A Negotiating Agent Based on Expecting
        Lower Limit of Concession Function. In: Modern Approaches to Agent-based
        Complex Automated Negotiation. Studies in Computational Intelligence,
        vol 674. Springer, Cham. https://doi.org/10.1007/978-3-319-51563-2_11
    """

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.Atlas3.Atlas3"
        super().__init__(**kwargs)


class CUHKAgent2015(GeniusNegotiator):
    """CUHKAgent2015 implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.cuhkagent2015.CUHKAgent2015"
        super().__init__(**kwargs)


class DrageKnight(GeniusNegotiator):
    """DrageKnight implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.DrageKnight.DrageKnight"
        super().__init__(**kwargs)


class Group2(GeniusNegotiator):
    """Group2 implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.group2.Group2"
        super().__init__(**kwargs)


class JonnyBlack(GeniusNegotiator):
    """JonnyBlack implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.JonnyBlack.JonnyBlack"
        super().__init__(**kwargs)


class Kawaii(GeniusNegotiator):
    """
    Kawaii negotiation agent.

    **ANAC 2015 Individual Utility Category Runner-up**.

    Kawaii is a negotiation agent that uses Simulated Annealing for bid
    search and a time-dependent conceding strategy. It adapts its
    acceptance threshold based on the number of accepting opponents in
    multilateral negotiations.

    **Offering Strategy:**
        Uses Simulated Annealing to search for bids near the target utility:

        1. First attempts relative utility search (for linear utility spaces)
           by selecting values that sum to the target concession amount
        2. Falls back to Simulated Annealing with parameters:
           - Start temperature: 1.0
           - End temperature: 0.0001
           - Cooling rate: 0.999

        The search minimizes the distance to target utility while staying
        above it. Returns the maximum utility bid if no suitable bid found.

    **Acceptance Strategy:**
        Time-dependent threshold with conceder behavior (exponent = 2):

        threshold(t) = 1 - (1 - a) * t^2

        where a = 0.8 is the minimum threshold.

        In multilateral scenarios, the threshold is reduced based on how
        many opponents have already accepted:

        threshold -= (threshold - minThreshold) * (acceptCount / numOpponents)

        This encourages acceptance when close to agreement.

    **Opponent Modeling:**
        Tracks which opponents have made accepting moves (offered bids
        close to previous offers). This information adjusts the acceptance
        threshold to facilitate agreement when multiple parties are close
        to consensus.

    References:
        Baarslag, T., Aydogan, R., Hindriks, K. V., Fujita, K., Ito, T., &
        Jonker, C. M. (2015). The Automated Negotiating Agents Competition,
        2010-2015. AI Magazine, 36(4), 115-118.
    """

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.fairy.kawaii"
        super().__init__(**kwargs)


class MeanBot(GeniusNegotiator):
    """MeanBot implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.meanBot.MeanBot"
        super().__init__(**kwargs)


class Mercury(GeniusNegotiator):
    """Mercury implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.Mercury.Mercury"
        super().__init__(**kwargs)


class PNegotiator(GeniusNegotiator):
    """P negotiator."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.pnegotiator.PNegotiator"
        super().__init__(**kwargs)


class ParsAgent(GeniusNegotiator):
    """
    ParsAgent negotiation agent.

    **ANAC 2015 Individual Utility Category Finalist**.

    ParsAgent by Zahra Khosravimehr from Amirkabir University of Technology
    uses a hybrid bidding strategy combining time-dependent, random, and
    frequency-based approaches to propose high-utility offers close to
    opponent preferences, increasing the likelihood of early agreement.

    **Offering Strategy:**
        Employs a multi-step bid generation process:

        1. First checks if there's a mutually beneficial bid from the
           intersection of both opponents' preferences (in multilateral).
        2. If not found, constructs a bid using:
           - Mutual issue values (agreed by both opponents based on frequency)
           - Own best values for non-mutual issues
        3. Falls back to modifying the best bid on the worst-weighted issue

        Target utility follows Boulware-style concession:

        target(t) = 1 - t^(1/e)

        where e = 0.15 (or 0.2 with discount factor). Minimum threshold is 0.7.

    **Acceptance Strategy:**
        Simple time-dependent acceptance: accepts if opponent's offer
        utility exceeds the target utility at current time. The target
        decreases from 1.0 towards 0.7 following the Boulware curve.

    **Opponent Modeling:**
        Frequency-based modeling for each opponent:

        - Tracks repeated values for each issue across opponent bids
        - Identifies mutual preferences between opponents (values both
          opponents frequently request)
        - Maintains sorted list of opponent bids by utility
        - Searches for Nash-like outcomes using common preferences

    References:
        Khosravimehr, Z., & Nassiri-Mofakham, F. (2017). Pars Agent: Hybrid
        Time-Dependent, Random and Frequency-Based Bidding and Acceptance
        Strategies in Multilateral Negotiations. In Fujita, K., et al.
        Modern Approaches to Agent-based Complex Automated Negotiation.
        Studies in Computational Intelligence, vol 674. Springer, Cham.
    """

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.ParsAgent.ParsAgent"
        super().__init__(**kwargs)


class PhoenixParty(GeniusNegotiator):
    """PhoenixParty implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.Phoenix.PhoenixParty"
        super().__init__(**kwargs)


class PokerFace(GeniusNegotiator):
    """PokerFace implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.pokerface.PokerFace"
        super().__init__(**kwargs)


class RandomDance(GeniusNegotiator):
    """
    RandomDance negotiation agent.

    **ANAC 2015 Individual Utility Category Finalist**.

    RandomDance Agent by Shinji Kakimoto proposes an opponent modeling
    approach using multiple weighted utility estimation functions. The
    agent randomly selects among different weighting schemes, making it
    unpredictable while still being responsive to opponent behavior.

    **Offering Strategy:**
        Searches for bids that balance self-utility with estimated opponent
        utility using weighted combination:

        1. For each issue, selects values that maximize weighted sum of
           estimated utilities across all parties
        2. Adjusts own weight iteratively (0 to 10) until finding a bid
           above the target utility
        3. Target utility is adaptive: starts at estimated Nash point and
           decreases following t^discount curve

        Falls back to best bid if no suitable bid found.

    **Acceptance Strategy:**
        Accepts based on target utility comparison with safety margin:

        - Tracks time per round to estimate remaining rounds
        - If remaining rounds <= 5, accepts to avoid negotiation failure
        - Otherwise accepts if opponent's offer exceeds target utility

    **Opponent Modeling:**
        Uses a library of multiple PlayerData models with different
        learning rates (delta = 1.0, 1.05, 0.55):

        - Each model tracks value frequencies with exponential weighting
        - Issue weights derived from maximum value frequencies
        - Randomly selects which model to use for each decision
        - Tracks Nash-optimal opponent (whose bids maximize product of
          estimated utilities) for weighting decisions

        Three weighting strategies randomly selected:
        1. Nash-based: weight by Nash optimality history
        2. Equal: all opponents weighted equally
        3. Alternating: alternate between opponents

    References:
        Kakimoto, S., & Fujita, K. (2017). RandomDance: Compromising Strategy
        Considering Interdependencies of Issues with Randomness. In Fujita, K.,
        et al. Modern Approaches to Agent-based Complex Automated Negotiation.
        Studies in Computational Intelligence, vol 674. Springer, Cham.
    """

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.RandomDance.RandomDance"
        super().__init__(**kwargs)


class SENGOKU(GeniusNegotiator):
    """SENGOKU implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.SENGOKU.SENGOKU"
        super().__init__(**kwargs)


class TUDMixedStrategyAgent(GeniusNegotiator):
    """TUDMixedStrategyAgent implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs[
            "java_class_name"
        ] = "agents.anac.y2015.TUDMixedStrategyAgent.TUDMixedStrategyAgent"
        super().__init__(**kwargs)


class XianFaAgent(GeniusNegotiator):
    """XianFaAgent implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.xianfa.XianFaAgent"
        super().__init__(**kwargs)


class Y2015Group2(GeniusNegotiator):
    """Y2015Group2 implementation."""

    def __init__(self, **kwargs):
        """Initialize the instance.

        Args:
            **kwargs: Additional keyword arguments.
        """
        kwargs["java_class_name"] = "agents.anac.y2015.group2.Group2"
        super().__init__(**kwargs)
