#!/usr/bin/python3
import json
import math
import os
import time
from datetime import datetime
import requests
import paho.mqtt.client as mqtt
# from src.services.tracker.rabbitmq_client import RabbitMQClient


def get_satellite_position(obs_lat=None,
                           obs_lon=None,
                           obs_alt=None,
                           sat_id=None,
                           future_samples=None,
                           url=None):
    # todo leerlo de config.cfg?
    if url:
        URL = url
    else:
        URL = "https://api.n2yo.com/rest/v1/satellite/"
    obs_lat = 41.702 if not obs_lat else obs_lat
    obs_lon = -76.014 if not obs_lon else obs_lon
    obs_alt = 0 if not obs_alt else obs_alt
    API_KEY = 'PFUNFH-BXYW5U-LJ7XME-4T7W'
    sat_id = 39084 if not sat_id else sat_id
    future_samples = 1 if not future_samples else future_samples
    operation = "positions/{}/{}/{}/{}/{}/&apiKey={}".format(sat_id,
                                                             obs_lat,
                                                             obs_lon,
                                                             obs_alt,
                                                             future_samples,
                                                             API_KEY)
    try:
        r = requests.get(URL + operation, verify=False).json()
    except Exception as ex:
        raise ex
    return r


def local_date_from_timestamp(r):
    timestamp = r["positions"][0]["timestamp"]
    dt_object = datetime.fromtimestamp(timestamp)
    r["positions"][0]["date"] = dt_object.strftime("%H:%M:%S")


def utc_from_timestamp(r):
    timestamp = r["positions"][0]["timestamp"]
    dt_object = datetime.utcfromtimestamp(timestamp)
    r["positions"][0]["utc"] = dt_object.strftime("%H:%M:%S")


def km_to_miles(r):
    km = r["positions"][0]["sataltitude"]
    miles = km * 0.621371
    r["positions"][0]["sataltitude_miles"] = miles


def format_ra(r):
    time = r["positions"][0]["ra"]
    degrees = int(time)
    res = time % int(time)
    minutes, res = divmod(res, 1 / 60)
    seconds, res = divmod(res, 1 / 3600)
    r["positions"][0]["ra"] = f'{degrees:02}:{minutes:02}:{seconds:02}'


def format_declination(r):
    time = r["positions"][0]["dec"]
    hours = int(time / 15)
    res = time % 15
    minutes = int(res / 0.25)
    res = res % 0.25
    seconds = int(res / (1 / 240))
    r["positions"][0]["ra"] = f'{hours:02}:{minutes:02}:{seconds:02}'


def update_speed(r, prev_lat, prev_lon, prev_alt, prev_timestamp):
    if (r["positions"][0]["timestamp"] - prev_timestamp) > 0:
        dist = math.sqrt(
            prev_alt ** 2 + r["positions"][0]["sataltitude"] ** 2 - 2 * prev_alt * r["positions"][0]["sataltitude"] *
            (math.cos(prev_lat) * math.cos(r["positions"][0]["satlatitude"]) *
             math.cos(prev_lon - r["positions"][0]["satlongitude"]) + math.sin(prev_lon) *
             math.sin(r["positions"][0]["satlongitude"]))
        )
        speed = dist / (r["positions"][0]["timestamp"] - prev_timestamp)
        r["positions"][0]["speed"] = speed
    else:
        pass


if __name__ == '__main__':
    prev_lat = 0
    prev_lon = 0
    prev_alt = 0
    prev_timestamp = 0
    data = {
        "SatName": "",
        "SatId": "",
        "RightAscension": "",
        "Declination": "",
        "Latitude": "",
        "Longitude": "",
        "UTC": "",
        "LocalDate": "",
        "Altitude": "",
        "Azimuth": "",
        "Elevation": "",
    }
    # rabbitmq_client = RabbitMQClient()
    mqtt_client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
    mqtt_client.connect(os.getenv("MQTT_HOST", 'localhost'), os.getenv('MQTT_PORT', 1883), 60)
    mqtt_topic = os.getenv("CLUSTER_NAME", "test/topic")
    while True:
        try:
            r = get_satellite_position()
            """local_date_from_timestamp(r)
            utc_from_timestamp(r)
            km_to_miles(r)
            format_ra(r)
            format_declination(r)
            # update_speed(r, prev_lat, prev_lon, prev_alt, prev_timestamp)
            r["positions"][0]["speed"] = 7.5
            r["positions"][0]["speed_miles"] = 4.66"""
            data = {
                # "SatName": r["info"]["satname"],
                "SatName": os.getenv('SATELLITE_NAME'),
                "SatId": os.getenv('SATELLITE_ID'),
                "LAtitude": r["positions"][0]["satlatitude"],
                "Longitude": r["positions"][0]["satlongitude"],
                "Altitude": r["positions"][0]["sataltitude"],
                "Azimuth": r["positions"][0]["azimuth"],
                "Elevation": r["positions"][0]["elevation"],
                "RA": r["positions"][0]["ra"],
                "Dec": r["positions"][0]["dec"],
                "Timestamp": r["positions"][0]["timestamp"],
                "Eclipsed": r["positions"][0]["eclipsed"]
            }
            try:
                # requests.put("http://0.0.0.0:5000/api/tracker/", json.dumps(data))
                # rabbitmq_client.send_message(json.dumps(data), "tracker")
                mqtt_client.publish(mqtt_topic, json.dumps(data), qos=0, retain=False)
            except Exception as ex:
                if isinstance(ex, ConnectionError):
                    time.sleep(60)
                else:
                    # rabbitmq_client.close_connection()
                    raise ex

            # print(f'A una velocidad de {r["positions"][0]["speed"]}')
            prev_lat = r["positions"][0]["satlatitude"]
            prev_lon = r["positions"][0]["satlongitude"]
            prev_alt = r["positions"][0]["sataltitude"]
            prev_timestamp = r["positions"][0]["timestamp"]
        except Exception as ex:
            # rabbitmq_client.close_connection()
            raise ex
        time.sleep(3)
