#!/usr/bin/env python3

''' A standalone nats-streaming consumer(subscriber) client to handle with the data from the channel named 'ev.user.* '''

import asyncio
import os
import signal
from nats.aio.client import Client as NATS
from stan.aio.client import Client as STAN
from conf import *


## 每个运行实例分别配置

# client id (每个运行实例唯一)
CLIENT_ID = 'consumer1'
# durable name 需要更多测试，来探测其性质                  
DURABLE_NAME = CLIENT_ID
# queue subscribe 模式使用,一般对应一个 subject
QUEUE_NAME = 'queue_ev_user'                         
# 订阅的 subject
SUBSCRIBE_TO = 'ev.test'
# 退出标记
CMD_QUIT = False


async def on_disconnected():
    print('lost connection to streaming nats')


async def on_closed():
    print('connection to streaming nats closed')


async def on_streaming_conn_lost():
    print('lost connection to streaming')


async def on_reconnect():
    print('start reconnecting to streaming nats.')


def on_signal(signum, frame):
    global CMD_QUIT
    print('received sigal, num=', signum)
    CMD_QUIT = True
    return


async def on_message(msg):
    print("Received a message (seq={}):-{}".format(msg.seq, msg.data))
    #TODO: do logic start from here


async def consume_infinitely(loop):
    nc = NATS()
    await nc.connect(
        name=CLIENT_ID,
        verbose=True,
        servers=STREAMING_SERVERS, 
        io_loop=loop, 
        user=STREAMING_USERNAME, 
        password=STREAMING_PASSWORD,
        disconnected_cb=on_disconnected,
        reconnected_cb=on_reconnect,
        closed_cb=on_closed,
        no_echo=False,
    )

    sc = STAN()
    await sc.connect(
        cluster_id=STREAMING_CLUSTER_ID, 
        client_id=CLIENT_ID, 
        nats=nc,
        conn_lost_cb=on_streaming_conn_lost,
    )
    
    sub = await sc.subscribe(SUBSCRIBE_TO, queue=QUEUE_NAME, durable_name=DURABLE_NAME, start_at="last_received", cb=on_message)

    signal.signal(signal.SIGINT, on_signal)
    print('press Ctrl + C to quit. this pid = ', os.getpid())

    async def wait_infinite():
        global CMD_QUIT
        while True:
            await asyncio.sleep(5)
            if CMD_QUIT:
                break
    
    await wait_infinite()

    await sub.unsubscribe()

    await sc.close()

    await nc.close()

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(consume_infinitely(loop))
    loop.close()
