# !/usr/bin/env python3

"""Crypto reporter"""

import json
import logging
import os
import requests
import time

from dotenv import load_dotenv
import paho.mqtt.client as mqtt


load_dotenv()  # Cargamos las variables de entorno necesarias

LOG_LEVEL = os.getenv('LOG_LEVEL', logging.INFO)

logging.basicConfig(level=LOG_LEVEL, format='[%(levelname)s] %(asctime)s - %(message)s')

BASE_API = 'https://api.coingecko.com/api/v3'

MQTT_TOPIC_DATA = os.getenv('MQTT_TOPIC_DATA', 'crypto-reporter/data')
MQTT_TOPIC_STATE = os.getenv('MQTT_TOPIC_STATE', 'crypto-reporter/state')

MQTT_PUBLISH_DELAY = int(os.getenv('MQTT_PUBLISH_DELAY', 60))
MQTT_CLIENT_ID = os.getenv('MQTT_CLIENT_ID', 'crypto-reporter')

MQTT_SERVER = os.getenv('MQTT_SERVER', 'localhost')
MQTT_PORT = int(os.getenv('MQTT_PORT', '1883'))
MQTT_USER = os.getenv('MQTT_USER', '')
MQTT_PASSWORD = os.getenv('MQTT_PASSWORD', '')

CRYPTOS_TO_PUBLISH = os.getenv('CRYPTOS_TO_PUBLISH', 'bitcoin')
CURRENCIES = os.getenv('CURRENCIES', 'eur')


def on_connect(client, userdata, flags, rc):
    logging.info("Connected to MQTT server.")
    client.publish(MQTT_TOPIC_STATE, 'connected', 1, True)


def main():
    logging.info(f'Connecting to MQTT host {MQTT_SERVER}:{MQTT_PORT}...')
    mqttc = mqtt.Client(MQTT_CLIENT_ID)
    mqttc.username_pw_set(MQTT_USER, MQTT_PASSWORD)
    mqttc.will_set(MQTT_TOPIC_STATE, 'disconnected', 1, True)
    mqttc.on_connect = on_connect

    mqttc.connect(MQTT_SERVER, MQTT_PORT, 60)
    mqttc.loop_start()
    last_msg_time = time.time()

    while True:
        try:
            x = requests.get(BASE_API + '/simple/price',
                             params={'ids': CRYPTOS_TO_PUBLISH,
                                     'vs_currencies': CURRENCIES})
            logging.debug(f'HTTP response: {x.status_code}')
            publish_data(mqttc, x.text)

            delay_gap = time.time() - last_msg_time
            if delay_gap < MQTT_PUBLISH_DELAY:
                time.sleep(MQTT_PUBLISH_DELAY - delay_gap)
            last_msg_time = time.time()

        except KeyboardInterrupt:
            logging.info("exiting...")
            exit(0)
        except Exception:
            logging.exception("something went wrong.")
            exit(1)


def publish_data(mqttc, raw):
    try:
        logging.debug(f'RAW message to publish: {raw}')
        data = json.loads(raw)
        for crypto in data:
            currencies = data[crypto]
            for currency in currencies:
                mqttc.publish(MQTT_TOPIC_DATA + f'/{crypto}/{currency}', data[crypto][currency], 1, True)
    except AttributeError:
        logging.exception("Error decoding JSON")


if __name__ == '__main__':
    logging.info('Starting crypto broker')
    main()