from threading import Thread

import cmsgbus
from assertpy import (
    assert_that,
)
from messagebus import (
    Event,
    Message,
)
from msgbus import (
    MBContext,
    MBService,
)


def test_event_published_from_python_is_received_on_msgbus(
    hv_address,
    hv_port,
):
    publisher = MBContext(
        my_service=MBService(
            address="127.0.0.1",
            port=14580,
        ),
        name="Publisher",
    )

    c_subscriber = cmsgbus.MBContext(
        my_service=cmsgbus.MBService(
            address="127.0.0.1",
            port=14581,
        ),
        name="Subscriber",
    )

    c_hv_service = cmsgbus.MBService(
        address=hv_address,
        port=hv_port,
    )

    hv_service = MBService(
        address=hv_address,
        port=hv_port,
    )

    subject = "MY_EVENT"
    event_type = "MY_TYPE"
    event_data = "EVENT_DATA"

    def publisher_thread():

        publisher.MB_EvtSend(
            hv_service=hv_service,
            subject=subject,
            type=event_type,
            xml=event_data,
            synchronous=False,
        )

    c_subscriber.MB_EvtSubscribe(
        hv_service=c_hv_service,
        subject=subject,
    )

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

    event = c_subscriber.MB_GetMessage()
    event = Event.build_from_message(
        message=Message(
            token=event.token,
            data_type=event.format,
            data=event.data,
        ),
    )
    assert_that(event.subject).is_equal_to(subject)
    assert_that(event.event_type).is_equal_to(event_type)
    assert_that(event.data).is_equal_to(event_data.encode())
    assert_that(event.synchronous).is_false()

    t.join()

    publisher.MB_Finalize()
    c_subscriber.MB_Finalize()


def test_event_published_from_msgbus_is_received_on_python(
    hv_address,
    hv_port,
):
    c_publisher = cmsgbus.MBContext(
        my_service=cmsgbus.MBService(
            address="127.0.0.1",
            port=14580,
        ),
        name="Publisher",
    )

    subscriber = MBContext(
        my_service=MBService(
            address="127.0.0.1",
            port=14581,
        ),
        name="Subscriber",
    )

    c_hv_service = cmsgbus.MBService(
        address=hv_address,
        port=hv_port,
    )

    hv_service = MBService(
        address=hv_address,
        port=hv_port,
    )

    subject = "MY_EVENT"
    event_type = "MY_TYPE"
    event_data = "EVENT_DATA"

    def publisher_thread():

        c_publisher.MB_EvtSend(
            hv_service=c_hv_service,
            subject=subject,
            type=event_type,
            xml=event_data,
            synchronous=False,
        )

    subscriber.MB_EvtSubscribe(
        hv_service=hv_service,
        subject=subject,
    )

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

    event = subscriber.MB_GetMessage()
    event = Event.build_from_message(
        message=Message(
            token=event.token,
            data_type=event.format,
            data=event.data,
        ),
    )
    assert_that(event.subject).is_equal_to(subject)
    assert_that(event.event_type).is_equal_to(event_type)
    assert_that(event.data).is_equal_to(event_data.encode())
    assert_that(event.synchronous).is_false()

    t.join()

    c_publisher.MB_Finalize()
    subscriber.MB_Finalize()

def test_event_published_from_python_is_received_on_python(
    hv_address,
    hv_port,
):
    publisher = MBContext(
        my_service=MBService(
            address="127.0.0.1",
            port=14580,
        ),
        name="Publisher",
    )

    subscriber = MBContext(
        my_service=MBService(
            address="127.0.0.1",
            port=14581,
        ),
        name="Subscriber",
    )

    hv_service = MBService(
        address=hv_address,
        port=hv_port,
    )

    subject = "MY_EVENT"
    event_type = "MY_TYPE"
    event_data = "EVENT_DATA"

    def publisher_thread():

        publisher.MB_EvtSend(
            hv_service=hv_service,
            subject=subject,
            type=event_type,
            xml=event_data,
            synchronous=False,
        )

    subscriber.MB_EvtSubscribe(
        hv_service=hv_service,
        subject=subject,
    )

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

    event = subscriber.MB_GetMessage()
    event = Event.build_from_message(
        message=Message(
            token=event.token,
            data_type=event.format,
            data=event.data,
        ),
    )
    assert_that(event.subject).is_equal_to(subject)
    assert_that(event.event_type).is_equal_to(event_type)
    assert_that(event.data).is_equal_to(event_data.encode())
    assert_that(event.synchronous).is_false()

    t.join()

    publisher.MB_Finalize()
    subscriber.MB_Finalize()
