import datetime
import logging
import time
import tracemalloc

from oslo_config import cfg

from aprsd import client, packets, utils
from aprsd.stats import collector
from aprsd.threads import APRSDThread, APRSDThreadList


CONF = cfg.CONF
LOG = logging.getLogger("APRSD")


class KeepAliveThread(APRSDThread):
    cntr = 0
    checker_time = datetime.datetime.now()

    def __init__(self):
        tracemalloc.start()
        super().__init__("KeepAlive")
        max_timeout = {"hours": 0.0, "minutes": 2, "seconds": 0}
        self.max_delta = datetime.timedelta(**max_timeout)

    def loop(self):
        if self.loop_count % 60 == 0:
            stats_json = collector.Collector().collect()
            pl = packets.PacketList()
            thread_list = APRSDThreadList()
            now = datetime.datetime.now()

            if "EmailStats" in stats_json:
                email_stats = stats_json["EmailStats"]
                if email_stats.get("last_check_time"):
                    email_thread_time = utils.strfdelta(now - email_stats["last_check_time"])
                else:
                    email_thread_time = "N/A"
            else:
                email_thread_time = "N/A"

            if "APRSClientStats" in stats_json and stats_json["APRSClientStats"].get("transport") == "aprsis":
                if stats_json["APRSClientStats"].get("server_keepalive"):
                    last_msg_time = utils.strfdelta(now - stats_json["APRSClientStats"]["server_keepalive"])
                else:
                    last_msg_time = "N/A"
            else:
                last_msg_time = "N/A"

            tracked_packets = stats_json["PacketTrack"]["total_tracked"]
            tx_msg = 0
            rx_msg = 0
            if "PacketList" in stats_json:
                msg_packets = stats_json["PacketList"].get("MessagePacket")
                if msg_packets:
                    tx_msg = msg_packets.get("tx", 0)
                    rx_msg = msg_packets.get("rx", 0)

            keepalive = (
                "{} - Uptime {} RX:{} TX:{} Tracker:{} Msgs TX:{} RX:{} "
                "Last:{} Email: {} - RAM Current:{} Peak:{} Threads:{}"
            ).format(
                stats_json["APRSDStats"]["callsign"],
                stats_json["APRSDStats"]["uptime"],
                pl.total_rx(),
                pl.total_tx(),
                tracked_packets,
                tx_msg,
                rx_msg,
                last_msg_time,
                email_thread_time,
                stats_json["APRSDStats"]["memory_current_str"],
                stats_json["APRSDStats"]["memory_peak_str"],
                len(thread_list),
            )
            LOG.info(keepalive)
            if "APRSDThreadList" in stats_json:
                thread_list = stats_json["APRSDThreadList"]
                for thread_name in thread_list:
                    thread = thread_list[thread_name]
                    alive = thread["alive"]
                    age = thread["age"]
                    key = thread["name"]
                    if not alive:
                        LOG.error(f"Thread {thread}")
                    LOG.info(f"{key: <15} Alive? {str(alive): <5} {str(age): <20}")

            # check the APRS connection
            cl = client.factory.create()
            # Reset the connection if it's dead and this isn't our
            # First time through the loop.
            # The first time through the loop can happen at startup where
            # The keepalive thread starts before the client has a chance
            # to make it's connection the first time.
            if not cl.is_alive() and self.cntr > 0:
                LOG.error(f"{cl.__class__.__name__} is not alive!!! Resetting")
                client.factory.create().reset()
            # else:
            #     # See if we should reset the aprs-is client
            #     # Due to losing a keepalive from them
            #     delta_dict = utils.parse_delta_str(last_msg_time)
            #     delta = datetime.timedelta(**delta_dict)
            #
            #     if delta > self.max_delta:
            #         #  We haven't gotten a keepalive from aprs-is in a while
            #         # reset the connection.a
            #         if not client.KISSClient.is_enabled():
            #             LOG.warning(f"Resetting connection to APRS-IS {delta}")
            #             client.factory.create().reset()

            # Check version every day
            delta = now - self.checker_time
            if delta > datetime.timedelta(hours=24):
                self.checker_time = now
                level, msg = utils._check_version()
                if level:
                    LOG.warning(msg)
            self.cntr += 1
        time.sleep(1)
        return True
