from __future__ import annotations
from dataclasses import dataclass
from Transaction import Transaction
from typing import TYPE_CHECKING
from uuid import uuid4

if TYPE_CHECKING:
    from TransactionDeliverer import TransactionDeliverer

@dataclass
class Message:
    message_id: str
    sender: str
    receiver: str

    # Returns if the message needs to be rebroadcast
    # for reliable multicast.
    # This is TRUE only if receiving a multicasted message,
    # not a unicasted message
    def receive_action(self):
        raise NotImplementedError("This is an abstract method that should never be called")

@dataclass
class TransactionMessage(Message):
    transaction: Transaction
    transaction_ID: str
    deliverable: bool = False
    
    def receive_action(self, td: TransactionDeliverer) -> bool:
        td.process_transaction_message(self)
        return True

@dataclass
class ProposedPriorityMessage(Message):
    transaction_ID: str
    proposed_priority: int

    def receive_action(self, td: TransactionDeliverer) -> bool:
        td.process_proposed_priority_message(self)
        return False
    

@dataclass
class AgreedPriorityMessage(Message):
    transaction_ID: str
    agreed_priority: int
    proposer: str

    def receive_action(self, td: TransactionDeliverer) -> bool:
        td.process_agreed_priority_message(self)
        return True