import json
import time
import traceback

from transport.rabbitmq import connection, exchanges, pool


def publish_without_producer(body: dict, exchange: str, routing_key: str):
    with pool.acquire() as channel:
        prod = connection.Producer(channel)
        prod.publish(body,
                     exchange=exchange,
                     routing_key=routing_key,
                     retry=True)

        
def publish_with_producer(body: dict, exchange: str, routing_key: str, producer):
    producer.publish(body,
                     exchange=exchange,
                     routing_key=routing_key,
                     retry=True)

        
def send_log(message, level="INFO", producer=None):
    try:
        if not isinstance(message, dict):
            message = {"message": message}

        kwargs = {
            "body": message,
            "exchange": exchanges.get('log'),
            "routing_key": level.lower()
        }

        if not producer:
            publish_without_producer(**kwargs)
        else:
            kwargs["producer"] = producer
            publish_with_producer(**kwargs)

    except Exception:
        raise Exception(f"{traceback.format_exc()}")


def send_ws_update(message):
    """sending update front state via websocket"""
    try:
        kwargs = {
            "body": message,
            "exchange": exchanges.get("websocket"),
            "routing_key": f"ws"
        }
        publish_without_producer(**kwargs)
    except Exception:
        raise Exception(f"{traceback.format_exc()}")


def send_websocket(message, level="info", access="root", producer=None):
    try:
        kwargs = {
            "body": message,
            "exchange": exchanges.get("websocket"),
            "routing_key": f"ws.{access}.{level}"
        }
        if not producer:
            publish_without_producer(**kwargs)
        else:
            kwargs["producer"] = producer
            publish_with_producer(**kwargs)
    except Exception:
        raise Exception(f"{traceback.format_exc()}")


def send_mqtt(topic, message, producer=None):
    try:
        kwargs = {
            "body": message,
            "exchange": exchanges.get('mqtt'),
            "routing_key": f"{topic}"
        }
        if not producer:
            publish_without_producer(**kwargs)
        else:
            publish_with_producer(producer=producer, **kwargs)
    except Exception:
        raise Exception(f"{traceback.format_exc()}")


def send_message_over_mqtt(topic, uid, command, payload=None):
    data = {"timestamp": int(time.time())}
    if payload:
        data["datahold"] = payload
    send_mqtt(f"{topic}.{uid}.{command}", data)


def save_device_payload(payload):
    timestamp = int(time.time())
    payload.update({"timestamp": timestamp})
    kwargs = {
        "body": payload,
        "exchange": exchanges.get('internal'),
        "routing_key": 'save'
    }
    publish_without_producer(**kwargs)
import json
import time
import traceback

from transport.rabbitmq import connection, exchanges, pool


def publish_without_producer(body: dict, exchange: str, routing_key: str):
    with pool.acquire() as channel:
        prod = connection.Producer(channel)
        prod.publish(body,
                     exchange=exchange,
                     routing_key=routing_key,
                     retry=True)

        
def publish_with_producer(body: dict, exchange: str, routing_key: str, producer):
    producer.publish(body,
                     exchange=exchange,
                     routing_key=routing_key,
                     retry=True)

        
def send_log(message, level="INFO", producer=None):
    try:
        if not isinstance(message, dict):
            message = {"message": message}

        kwargs = {
            "body": message,
            "exchange": exchanges.get('log'),
            "routing_key": level.lower()
        }

        if not producer:
            publish_without_producer(**kwargs)
        else:
            kwargs["producer"] = producer
            publish_with_producer(**kwargs)

    except Exception:
        raise Exception(f"{traceback.format_exc()}")


def send_ws_update(message):
    """sending update front state via websocket"""
    try:
        kwargs = {
            "body": message,
            "exchange": exchanges.get("websocket"),
            "routing_key": f"ws"
        }
        publish_without_producer(**kwargs)
    except Exception:
        raise Exception(f"{traceback.format_exc()}")


def send_websocket(message, level="info", access="root", producer=None):
    try:
        kwargs = {
            "body": message,
            "exchange": exchanges.get("websocket"),
            "routing_key": f"ws.{access}.{level}"
        }
        if not producer:
            publish_without_producer(**kwargs)
        else:
            kwargs["producer"] = producer
            publish_with_producer(**kwargs)
    except Exception:
        raise Exception(f"{traceback.format_exc()}")


def send_mqtt(topic, message, producer=None):
    try:
        kwargs = {
            "body": message,
            "exchange": exchanges.get('mqtt'),
            "routing_key": f"{topic}"
        }
        if not producer:
            publish_without_producer(**kwargs)
        else:
            publish_with_producer(producer=producer, **kwargs)
    except Exception:
        raise Exception(f"{traceback.format_exc()}")


def send_message_over_mqtt(topic, uid, command, payload=None):
    data = {"timestamp": int(time.time())}
    if payload:
        data["datahold"] = payload
    send_mqtt(f"{topic}.{uid}.{command}", data)


def save_device_payload(payload):
    timestamp = int(time.time())
    payload.update({"timestamp": timestamp})
    kwargs = {
        "body": payload,
        "exchange": exchanges.get('internal'),
        "routing_key": 'save'
    }
    publish_without_producer(**kwargs)
sending update front state via websocket