import logging
from datetime import datetime

import pytz

from core.cache_utils import SEMI_STATIC_URL_DATA_CACHE
from core.constants import HTTP_HEADERS
from data.sig_ref import SIGRef
from data.spot import Spot
from spotproviders.http_spot_provider import HTTPSpotProvider


class GMA(HTTPSpotProvider):
    """Spot provider for General Mountain Activity"""

    POLL_INTERVAL_SEC = 120
    SPOTS_URL = "https://www.cqgma.org/api/spots/25/"
    # GMA spots don't contain the details of the programme they are for, we need a separate lookup for that
    REF_INFO_URL_ROOT = "https://www.cqgma.org/api/ref/?"

    def __init__(self, provider_config):
        super().__init__(provider_config, self.SPOTS_URL, self.POLL_INTERVAL_SEC)

    def _http_response_to_spots(self, http_response):
        new_spots = []
        # Iterate through source data
        for source_spot in http_response.json()["RCD"]:
            # Convert to our spot format
            spot = Spot(source=self.name,
                        dx_call=source_spot["ACTIVATOR"].upper(),
                        de_call=source_spot["SPOTTER"].upper(),
                        freq=float(source_spot["QRG"]) * 1000 if (source_spot["QRG"] != "") else None,
                        # Seen GMA spots with no frequency
                        mode=source_spot["MODE"].upper() if "<>" not in source_spot["MODE"] else None,
                        # Filter out some weird mode strings
                        comment=source_spot["TEXT"],
                        sig_refs=[SIGRef(id=source_spot["REF"], sig="", name=source_spot["NAME"])],
                        time=datetime.strptime(source_spot["DATE"] + source_spot["TIME"], "%Y%m%d%H%M").replace(
                            tzinfo=pytz.UTC).timestamp(),
                        dx_latitude=float(source_spot["LAT"]) if (
                                source_spot["LAT"] and source_spot["LAT"] != "") else None,
                        # Seen GMA spots with no (or empty) lat/lon
                        dx_longitude=float(source_spot["LON"]) if (
                                source_spot["LON"] and source_spot["LON"] != "") else None)

            # GMA doesn't give what programme (SIG) the reference is for until we separately look it up.
            if "REF" in source_spot:
                try:
                    ref_response = SEMI_STATIC_URL_DATA_CACHE.get(self.REF_INFO_URL_ROOT + source_spot["REF"],
                                                                  headers=HTTP_HEADERS)
                    # Sometimes this is blank, so handle that
                    if ref_response.text is not None and ref_response.text != "":
                        ref_info = ref_response.json()
                        # If this is POTA, SOTA or WWFF data we already have it through other means, so ignore. POTA and WWFF
                        # spots come through with reftype=POTA or reftype=WWFF. SOTA is harder to figure out because both SOTA
                        # and GMA summits come through with reftype=Summit, so we must check for the presence of a "sota" entry
                        # to determine if it's a SOTA summit.
                        if spot.sig_refs and "reftype" in ref_info and ref_info["reftype"] not in ["POTA", "WWFF"] and (
                                ref_info["reftype"] != "Summit" or "sota" not in ref_info or ref_info["sota"] == ""):
                            match ref_info["reftype"]:
                                case "Summit":
                                    spot.sig_refs[0].sig = "GMA"
                                    spot.sig = "GMA"
                                case "IOTA Island":
                                    spot.sig_refs[0].sig = "IOTA"
                                    spot.sig = "IOTA"
                                case "Lighthouse (ILLW)":
                                    spot.sig_refs[0].sig = "ILLW"
                                    spot.sig = "ILLW"
                                case "Lighthouse (ARLHS)":
                                    spot.sig_refs[0].sig = "ARLHS"
                                    spot.sig = "ARLHS"
                                case "Castle":
                                    spot.sig_refs[0].sig = "WCA"
                                    spot.sig = "WCA"
                                case "Mill":
                                    spot.sig_refs[0].sig = "MOTA"
                                    spot.sig = "MOTA"
                                case _:
                                    logging.warning("GMA spot found with ref type " + ref_info[
                                        "reftype"] + ", developer needs to add support for this!")
                                    spot.sig_refs[0].sig = ref_info["reftype"]
                                    spot.sig = ref_info["reftype"]

                            # Add to our list. Don't worry about de-duping, removing old spots etc. at this point; other code will do
                            # that for us.
                            new_spots.append(spot)
                except:
                    logging.warning("Exception when looking up " + self.REF_INFO_URL_ROOT + source_spot[
                        "REF"] + ", ignoring this spot for now")
        return new_spots
