from threading import Thread

import cmsgbus
import msgbus
from assertpy import assert_that


def test_send_message_from_python_is_received_on_msgbus():
    server_ip = "127.0.0.1"
    sender_port = 14581
    receiver_port = 14580
    dest_name = "a service"

    old_mb_context = cmsgbus.MBContext(
        my_service=cmsgbus.MBService(
            address=server_ip,
            port=receiver_port,
        ),
        name="old service",
    )

    new_mb_context = msgbus.MBContext(
        my_service=msgbus.MBService(
            address=server_ip,
            port=sender_port,
        ),
        name="new service",
    )

    send_and_receive(
        sender=new_mb_context,
        destination=msgbus.MBService(
            address=server_ip,
            port=receiver_port,
            name=dest_name,
        ),
        dest_name=dest_name,
        receiver=old_mb_context,
        server_ip=server_ip,
        message_count=100,
    )

    old_mb_context.MB_Finalize()
    new_mb_context.MB_Finalize()

def test_message_from_msgbus_is_received_on_python():
    server_ip = "127.0.0.1"
    sender_port = 14581
    receiver_port = 14580
    dest_name = "a service"

    old_mb_context = cmsgbus.MBContext(
        my_service=cmsgbus.MBService(
            address=server_ip,
            port=sender_port,
        ),
        name="old service",
    )

    new_mb_context = msgbus.MBContext(
        my_service=msgbus.MBService(
            address=server_ip,
            port=receiver_port,
        ),
        name="new service",
    )

    send_and_receive(
        sender=old_mb_context,
        destination=cmsgbus.MBService(
            address=server_ip,
            port=receiver_port,
            pservice=dest_name,
        ),
        dest_name=dest_name,
        receiver=new_mb_context,
        server_ip=server_ip,
        message_count=100,
    )

    old_mb_context.MB_Finalize()
    new_mb_context.MB_Finalize()


def test_message_from_python_is_received_on_python():
    server_ip = "127.0.0.1"
    sender_port = 14581
    receiver_port = 14580
    dest_name = "a service"

    old_mb_context = msgbus.MBContext(
        my_service=msgbus.MBService(
            address=server_ip,
            port=sender_port,
        ),
        name="old service",
    )

    new_mb_context = msgbus.MBContext(
        my_service=msgbus.MBService(
            address=server_ip,
            port=receiver_port,
        ),
        name="new service",
    )

    send_and_receive(
        sender=old_mb_context,
        destination=msgbus.MBService(
            address=server_ip,
            port=receiver_port,
            name=dest_name,
        ),
        dest_name=dest_name,
        receiver=new_mb_context,
        server_ip=server_ip,
        message_count=100,
    )

    old_mb_context.MB_Finalize()
    new_mb_context.MB_Finalize()

def send_and_receive(
    sender: msgbus.MBContext,
    destination: msgbus.MBService,
    dest_name: str,
    receiver: msgbus.MBContext,
    server_ip: str,
    message_count: int,
):
    sent_token = msgbus.TK_CMP_GETSERVICES
    sent_format = msgbus.FM_STRING
    sent_data = b"some data"
    sent_headers = b"some headers"
    sent_ttl = 30

    reply_token = msgbus.TK_SYS_ACK
    reply_format = msgbus.FM_STRING
    reply_data = b"reply_data"

    def receive_thread():
        for _ in range(message_count):
            received = receiver.MB_GetMessage()

            assert_that(received.token).is_equal_to(sent_token)
            assert_that(received.format).is_equal_to(sent_format)
            assert_that(received.ttl).is_equal_to(sent_ttl)
            assert_that(received.data).is_equal_to(sent_data)
            assert_that(received.headers).is_equal_to(sent_headers)
            assert_that(received.destname).is_equal_to(dest_name)
            assert_that(received.remotehost).is_equal_to(server_ip)

            received.token = reply_token
            receiver.MB_ReplyMessage(
                message=received,
                format=reply_format,
                data=reply_data,
            )

    Thread(target=receive_thread).start()

    for _ in range(message_count):
        reply = sender.MB_SendFullMessage(
            destination=destination,
            token=sent_token,
            format=sent_format,
            data=sent_data,
            headers=sent_headers,
            timeout=5000000000,
            ttl=sent_ttl,
        )

        assert_that(reply.token).is_equal_to(reply_token)
        assert_that(reply.format).is_equal_to(reply_format)
        assert_that(reply.data).is_equal_to(reply_data)
        assert_that(reply.remotehost).is_equal_to(server_ip)
