from command import TxCommand
import api_validations
import base64
from queue import Queue
from arq_session_iss import ARQSessionISS
from message_p2p import MessageP2P
from arq_data_type_handler import ARQ_SESSION_TYPES
from message_system_db_manager import DatabaseManager
from message_system_db_messages import DatabaseManagerMessages
import threading
import numpy as np


class SendMessageCommand(TxCommand):
    """Command to send a P2P message using an ARQ transfer session
    """

    def set_params_from_api(self, apiParams):
        """Sets parameters from the API request.

        This method creates a MessageP2P object from the API parameters,
        and adds the message to the database with the status 'queued'.

        Args:
            apiParams (dict): A dictionary containing the API parameters.
        """
        origin = f"{self.config['STATION']['mycall']}-{self.config['STATION']['myssid']}"
        self.message = MessageP2P.from_api_params(origin, apiParams)
        DatabaseManagerMessages(self.event_manager).add_message(self.message.to_dict(), statistics={}, direction='transmit', status='queued', frequency=self.state_manager.radio_frequency)

    def transmit(self, modem):
        """Transmits the first queued message using ARQ.

        This method retrieves the first queued message from the database,
        prepares the data using the ARQ data type handler, creates an
        ARQSessionISS, and starts the transmission. It includes error
        handling and logging.

        Args:
            modem: The modem object.
        """
        if self.state_manager.getARQ():
            self.log("Modem busy, waiting until ready...")
            return

        if not modem:
            self.log("Modem not running...", isWarning=True)
            return

        first_queued_message = DatabaseManagerMessages(self.event_manager).get_first_queued_message()
        if not first_queued_message:
            self.log("No queued message in database.")
            return
        try:
            self.log(f"Queued message found: {first_queued_message['id']}")
            DatabaseManagerMessages(self.event_manager).update_message(first_queued_message["id"], update_data={'status': 'transmitting'}, frequency=self.state_manager.radio_frequency)
            message_dict = DatabaseManagerMessages(self.event_manager).get_message_by_id(first_queued_message["id"])
            message = MessageP2P.from_api_params(message_dict['origin'], message_dict)

            # wait some random time and wait if we have an ongoing codec2 transmission
            # on our channel. This should prevent some packet collision
            random_delay = np.random.randint(0, 6)
            threading.Event().wait(random_delay)
            while self.state_manager.is_receiving_codec2_signal():
                threading.Event().wait(0.1)

            # Convert JSON string to bytes (using UTF-8 encoding)
            payload = message.to_payload().encode('utf-8')
            json_bytearray = bytearray(payload)
            data, data_type = self.arq_data_type_handler.prepare(json_bytearray, ARQ_SESSION_TYPES.p2pmsg_zlib)
            iss = ARQSessionISS(self.config,
                                modem,
                                self.message.destination,
                                self.state_manager,
                                data,
                                data_type
                                )
            self.state_manager.register_arq_iss_session(iss)
            iss.start()
        except Exception as e:
            self.log(f"Error starting ARQ session: {e}", isWarning=True)
