from __future__ import annotations

from typing import TYPE_CHECKING

from aasm.intermediate.message import Message
from aasm.utils.validation import is_valid_name, print_invalid_names

if TYPE_CHECKING:
    from aasm.parsing.state import State


def op_MESSAGE(state: State, msg_type: str, msg_performative: str) -> None:
    state.require(not state.in_message, 'Already inside a message.', 'First end current message using EMESSAGE.')
    state.require(not state.in_agent, 'Cannot define messages inside agents.', 'First end current agent using EAGENT.')
    state.require(not state.in_graph, 'Cannot define messages inside graphs.', 'First end current graph using EGRAPH.')
    state.require(
        not state.message_exists(msg_type, msg_performative), 
        f'Message {msg_type}/{msg_performative} already exists in the current environment.'
    )
    state.require(
        is_valid_name(msg_type), 
        f'{msg_type} is not a correct name.', 
        f'Names can only contain alphanumeric characters, underscores and cannot be: {print_invalid_names()}.'
    )
    state.require(
        is_valid_name(msg_performative), 
        f'{msg_performative} is not a correct name.', 
        f'Names can only contain alphanumeric characters, underscores and cannot be: {print_invalid_names()}.'
    )
    
    state.in_message = True
    state.add_message(Message(msg_type, msg_performative))


def op_EMESSAGE(state: State) -> None:    
    state.require(state.in_message, 'Not inside any message.', 'Try defining new messages using MESSAGE.')
    
    state.in_message = False
