from olives_gamestate import GameState
from olives_object import Object, MessageType
from olives_types import Position2
from olives_object_type import ObjectType


class AbstractObject:
    """
    This is the base class for the interactive object behaviour.
    Do not mistake this class with the Object and ControllableObject classes,
    as their purpose is to act as an interface to the Object C++ class.

    The "olives" prefix in the file indicates it is not meant to be edited,
    as this will most definitely result in breakage.
    """

    object_id = 0

    def __init__(self, object_type_name: str, object_id: int, object_type: ObjectType):
        """
        Initialises an object

        :param object_type_name Readable object name
        :param object_id The object's unique id
        :param object_type The object type's configuration
        """
        self.object_id = object_id

    def on_tick(self, obj: Object, elapsed_ticks: int, game_state: GameState, temperature: int):
        """
        Called every third tick or every 30th tick with objects in the FewTicksRequired category.
        Used for arbitrary game logic.

        :param obj: Reference to the actual C++ object, as exposed in Python
        :param elapsed_ticks: The actual number of elapsed ticks
        :param game_state: Reference to the actual C++ game state, as exposed in Python. To be used for synchronous calls, unlike job messages.
        :param temperature: The temperature at the position of the object, pre-fetched on the C++ side in order to not to do a unnecessary call each tick
        """
        pass

    def on_create(self, obj: Object, pos: Position2):
        """ Called after creating an object """
        pass

    def on_move(self, obj: Object, pos: Position2):
        """ Called after the user moved a non-controllable object (not to be confused with navigation) """
        pass

    def on_remove(self, obj: Object, pos: Position2):
        """ Called after the user removed a non-controllable object """
        pass

    def on_enable(self, obj: Object):
        """ Called when a togglable object is being enabled """
        pass

    def on_disable(self, obj: Object):
        """ Called when a togglable object is being disabled """
        pass

    @staticmethod
    def add_job_message(obj: Object, message_type: MessageType, context_id: int, context_param: str = "",
                        pos1: Position2 = None, pos2: Position2 = None):
        """
        Sends an asynchronous message to be consumed by the game state

        :param obj: Reference to the C++ object, as exposed to Python
        :param message_type: The type of message to send/action to be triggered
        :param context_id: Arbitrary context ID depending on message type (e.g. object_id)
        :param context_param: Arbitrary context string depending on message type
        :param pos1: Arbitrary position depending on message type
        :param pos2: Arbitrary position depending on message type
        """

        if pos1 is None:
            pos1 = Position2(0, 0)
        if pos2 is None:
            pos2 = Position2(0, 0)
        obj.add_job_message(message_type, context_id, context_param, pos1, pos2)
