from threading import Thread

import msgbus
from assertpy import assert_that
from msgbus import (
    MBContext,
    MBService,
    TK_SYS_ACK,
)

_SERVER_IP = "127.0.0.1"
_SERVER_PORT = 14596
_SENDER_PORT = 14597


def test_send_message_with_str_data_is_received_correctly():

    server = MBContext(
        my_service=MBService(address=_SERVER_IP, port=_SERVER_PORT),
        name="server",
    )
    sender = MBContext(
        my_service=MBService(address=_SERVER_IP, port=_SENDER_PORT),
        name="sender",
    )
    sent_str = "hello as string"

    def server_thread():
        msg = server.MB_GetMessage()
        assert_that(msg.data).is_equal_to(sent_str.encode())
        msg.token = TK_SYS_ACK
        server.MB_ReplyMessage(message=msg, data=b"ok")

    t = Thread(target=server_thread)
    t.start()

    reply = sender.MB_SendFullMessage(
        destination=MBService(address=_SERVER_IP, port=_SERVER_PORT),
        token=msgbus.TK_CMP_GETSERVICES,
        data=sent_str,
    )

    assert_that(reply.token).is_equal_to(TK_SYS_ACK)

    t.join()
    server.MB_Finalize()
    sender.MB_Finalize()


def test_send_message_with_empty_str_data_is_received_correctly():

    server = MBContext(
        my_service=MBService(address=_SERVER_IP, port=_SERVER_PORT),
        name="server",
    )
    sender = MBContext(
        my_service=MBService(address=_SERVER_IP, port=_SENDER_PORT),
        name="sender",
    )

    def server_thread():
        msg = server.MB_GetMessage()
        assert_that(msg.data).is_equal_to(b"")
        msg.token = TK_SYS_ACK
        server.MB_ReplyMessage(message=msg, data=b"ok")

    t = Thread(target=server_thread)
    t.start()

    reply = sender.MB_SendFullMessage(
        destination=MBService(address=_SERVER_IP, port=_SERVER_PORT),
        token=msgbus.TK_CMP_GETSERVICES,
        data="",
    )

    assert_that(reply.token).is_equal_to(TK_SYS_ACK)

    t.join()
    server.MB_Finalize()
    sender.MB_Finalize()


def test_send_message_with_str_headers_is_received_correctly():

    server = MBContext(
        my_service=MBService(address=_SERVER_IP, port=_SERVER_PORT),
        name="server",
    )
    sender = MBContext(
        my_service=MBService(address=_SERVER_IP, port=_SENDER_PORT),
        name="sender",
    )
    sent_headers = "some-header-as-string"

    def server_thread():
        msg = server.MB_GetMessage()
        assert_that(msg.headers).is_equal_to(sent_headers.encode())
        msg.token = TK_SYS_ACK
        server.MB_ReplyMessage(message=msg, data=b"ok")

    t = Thread(target=server_thread)
    t.start()

    reply = sender.MB_SendFullMessage(
        destination=MBService(address=_SERVER_IP, port=_SERVER_PORT),
        token=msgbus.TK_CMP_GETSERVICES,
        headers=sent_headers,
    )

    assert_that(reply.token).is_equal_to(TK_SYS_ACK)

    t.join()
    server.MB_Finalize()
    sender.MB_Finalize()


def test_reply_message_with_str_data_is_received_correctly():

    server = MBContext(
        my_service=MBService(address=_SERVER_IP, port=_SERVER_PORT),
        name="server",
    )
    sender = MBContext(
        my_service=MBService(address=_SERVER_IP, port=_SENDER_PORT),
        name="sender",
    )
    reply_str = "reply as string"

    def server_thread():
        msg = server.MB_GetMessage()
        msg.token = TK_SYS_ACK
        server.MB_ReplyMessage(message=msg, data=reply_str)

    t = Thread(target=server_thread)
    t.start()

    reply = sender.MB_SendFullMessage(
        destination=MBService(address=_SERVER_IP, port=_SERVER_PORT),
        token=msgbus.TK_CMP_GETSERVICES,
        data=b"request",
    )

    assert_that(reply.token).is_equal_to(TK_SYS_ACK)
    assert_that(reply.data).is_equal_to(reply_str.encode())

    t.join()
    server.MB_Finalize()
    sender.MB_Finalize()
