#-------------------------------------------------------------------------------
# Name:        Order Protocol
# Purpose:     Demo for Delphi Day
#
# Author:      Marco Breveglieri
#-------------------------------------------------------------------------------

import os
import time
import json
import stomp
import pymongo


# RabbitMQ params
RABBITMQ_HOST = 'delphiday-rabbitmq'
RABBITMQ_PORT = 61613
RABBITMQ_USERNAME = 'root'
RABBITMQ_PASSWORD = 'delphi'
RABBITMQ_QUEUE_PROTOCOL = 'order-protocol'
RABBITMQ_QUEUE_RECEIVED = 'order-received'


# MongoDB params
MONGODB_USERNAME = 'root'
MONGODB_PASSWORD = 'delphi'
MONGODB_HOST = 'delphiday-mongo'
MONGODB_PORT = 27017
MONGODB_DATABASE = 'bakery'
MONGODB_COLLECTION = 'orders'


def connect_and_subscribe(conn):
    conn.connect(RABBITMQ_USERNAME, RABBITMQ_PASSWORD, wait=True)
    conn.subscribe(destination=f'/queue/{RABBITMQ_QUEUE_PROTOCOL}', id=1, ack='client')
    print('Connected')

def insert_order(order):
    db_url = 'mongodb://{username}:{password}@{host}:{port}/'.format(
        username=MONGODB_USERNAME,
        password=MONGODB_PASSWORD,
        host=MONGODB_HOST,
        port=MONGODB_PORT)
    db_client = pymongo.MongoClient(db_url)
    order_db = db_client[MONGODB_DATABASE]
    order_store = order_db[MONGODB_COLLECTION]
    order_store.insert_one(order)


class ProtocolListener(stomp.ConnectionListener):

    def __init__(self, conn):
        self.conn = conn

    def on_error(self, frame):
        print('Received an error "%s"' % frame.body)

    def on_message(self, frame):
        message_id = frame.headers['message-id']
        print('Order received in message: "%s"' % message_id)
        order_json = json.loads(frame.body)
        insert_order(order_json)
        print('Order saved')
        
        self.conn.send(destination=f'/queue/{RABBITMQ_QUEUE_RECEIVED}', body=frame.body)
        print('Order received')
        self.conn.ack(message_id, 1)

    def on_disconnected(self):
        print('Disconnected')
        connect_and_subscribe(self.conn)


# Attesa avvio sistemi correlati
time.sleep(15)

stomp_connection = stomp.Connection([(RABBITMQ_HOST, RABBITMQ_PORT)], heartbeats=(4000, 4000))
stomp_connection.set_listener('', ProtocolListener(stomp_connection))
connect_and_subscribe(stomp_connection)

try:
    while True:
        time.sleep(1)
finally:
    stomp_connection.disconnect()
