#!/usr/bin/env python3

# Test whether a bridge topics work correctly after reconnection.
# Important point here is that persistence is enabled.

from mosq_test_helper import *

def write_config(filename, port1, port2, protocol_version):
    with open(filename, 'w') as f:
        f.write("log_type all\n")
        f.write("listener %d\n" % (port2))
        f.write("plugin c/plugin_evt_persist_client_update.so\n")
        f.write("allow_anonymous true\n")
        f.write("persistent_client_expiration 1d\n")
        f.write("\n")
        f.write("connection connect_only_bridge\n")
        f.write("address 127.0.0.1:%d\n" % (port1))
        f.write("topic bridge/# out\n")
        f.write("bridge_protocol_version %s\n" % (protocol_version))
        f.write("bridge_max_topic_alias 0\n")
        f.write("cleansession false\n")
        f.write("notification_topic bridge_state\n")
        f.write("restart_timeout 300\n")


def do_test(proto_ver):
    bridge_protocol = "mqttv311" if proto_ver == 4 else "mqttv50"

    (port1, port2) = mosq_test.get_port(2)
    conf_file = '06-bridge-remote-shutdown.conf'
    write_config(conf_file, port1, port2, bridge_protocol)

    rc = 1
    connect_packet = mosq_test.gen_connect("test-client", proto_ver=proto_ver)
    connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
    mid = 180
    subscribe_packet = mosq_test.gen_subscribe(mid, "#", 0, proto_ver=proto_ver)
    suback_packet = mosq_test.gen_suback(mid, 0, proto_ver=proto_ver)
    publish_packet = mosq_test.gen_publish("echo_topic", qos=0, payload="sample-message", proto_ver=proto_ver)
    bridge_up_packet = mosq_test.gen_publish("bridge_state", qos=0, payload="1", retain=1, proto_ver=proto_ver)
    bridge_down_packet = mosq_test.gen_publish("bridge_state", qos=0, payload="0", retain=0, proto_ver=proto_ver)
    
    remote_broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port1, use_conf=False)

    local_cmd = [mosq_test.get_build_root() + '/src/mosquitto', '-c', conf_file]
    local_broker = mosq_test.start_broker(cmd=local_cmd, filename=os.path.basename(__file__)+'_local1', use_conf=False, port=port2)    

    rc1 = None
    
    try:
        sock = mosq_test.do_client_connect(connect_packet, connack_packet, port=port2)
        sock = mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback")

        mosq_test.expect_packet(sock, "check for bridge up state", bridge_up_packet)

        rc1, stde1 = mosq_test.terminate_broker(remote_broker)
        
        mosq_test.expect_packet(sock, "wait for bridge down state", bridge_down_packet)
        # If we now get a message published to evt/persist/client/update instead of the expected echo
        # the bridge connection was most likely added to the expiry list
        sock = mosq_test.do_send_receive(sock, publish_packet, publish_packet)

        rc = 0

        sock.close()
    except mosq_test.TestError:
        
        pass
    finally:
        if rc1 is None:
            rc1, stde1 = mosq_test.terminate_broker(remote_broker)
        rc2, stde2 = mosq_test.terminate_broker(local_broker)
        if rc or rc1 or rc2:
            print(f"Remote broker first run rc={rc1}")
            print(stde1.decode('utf-8'))

            print(f"Local broker rc={rc2}")
            print(stde2.decode('utf-8'))
        try: 
            os.remove(conf_file)
        except OSError:
            pass
    return rc == 0

if do_test(proto_ver=4) and do_test(proto_ver=5):
    exit(0)

exit(1)

