from datetime import datetime

import requests

from django.conf import settings
from django.contrib.gis.geos import fromstr
from django.core.cache import cache

from citytemp.models import City, Temperature

from spirithunter.logging import LogMixin

from ..models.elements import Element
from ..models.weather import WeatherCounter
from ..exceptions import ApiLimitExceeded

from .base import Arbiter


class WeatherArbiter(LogMixin, Arbiter):

    TEMPERATURE_THRESHOLD = 5
    WIND_THRESHOLD = 20
    WUNDERGROUND_KEY = "88882c941f645b5c"
    CACHE_TIME = 14400  # 4 hours

    CONDITION_SUNNY = "sun"
    CONDITIONS = (
        (CONDITION_SUNNY, "Sunny"),
    )

    WEIGHT_HOT = 7
    WEIGHT_COLD = 7
    WEIGHT_WIND = 15

    def __init__(self, lat, lng):
        """
        API call to get current weather conditions
        """

        self.centre = fromstr('POINT(%s %s)' % (lng, lat))
        self.city = City.objects.distance(self.centre).order_by("distance")[0]

        self.current_temperature = None
        self.wind = None
        self.conditions = None

        try:
            self._get_weather()
        except ApiLimitExceeded:
            self.logger.error("API limit exceeded :-(")
            # The default of None ensures that the weather tests are all False
            pass
        else:
            self.now = datetime.now()
            self.temperature = Temperature.objects.get(
                city=self.city,
                month=self.now.month,
                day=self.now.day
            )

    def get_results(self):

        r = {"elements": [], "facets": [], "nationalities": []}

        if self._is_hot():
            self.logger.debug("HOT!")
            r["elements"].append((Element.ELEMENT_HOT, self.WEIGHT_HOT))
        if self._is_cold():
            self.logger.debug("COLD!")
            r["elements"].append((Element.ELEMENT_COLD, self.WEIGHT_COLD))
        if self._is_windy():
            self.logger.debug("WINDY!")
            r["elements"].append((Element.ELEMENT_WIND, self.WEIGHT_WIND))

        return r

    def _is_hot(self):
        if self.current_temperature and self.temperature.mean:
            compare = self.temperature.mean + self.TEMPERATURE_THRESHOLD
            return self.current_temperature > compare
        return False

    def _is_cold(self):
        if self.current_temperature and self.temperature.mean:
            compare = self.temperature.mean - self.TEMPERATURE_THRESHOLD
            return self.current_temperature < compare
        return False

    def _is_windy(self):
        if self.wind:
            return self.wind > self.WIND_THRESHOLD
        return False

    def _get_weather(self):
        """
        API call to Wunderground for weather and temperature
        """

        if not settings.ONLINE:
            return {
                "temperature": 0,
                "wind": 0,
                "conditions": "sun"
            }

        self.logger.debug("Acquiring weather data for {city}".format(
            city=self.city.airport_code
        ))

        current_weather = cache.get(self.city.airport_code)

        if not current_weather:
            WeatherCounter.count()  # Might throw an ApiLimitExceeded exception
            self.logger.debug("Querying Wunderground")
            url = "http://{}/api/{}/conditions/q/{}/{}.json".format(
                "api.wunderground.com",
                self.WUNDERGROUND_KEY,
                self.city.country.code.upper(),
                self.city.airport_code.upper()
            )
            response = requests.get(url).json()
            self.logger.debug(response)
            wunderground = response.get("current_observation", {})
            current_weather = {
                "temperature": wunderground.get("temp_c"),
                "wind": wunderground.get("wind_kph"),
                "conditions": wunderground.get("icon")
            }
            cache.set(self.city.airport_code, current_weather, self.CACHE_TIME)
        self.logger.debug(current_weather)
        self.current_temperature = current_weather.get("temperature")
        self.conditions = current_weather.get("conditions")
        self.wind = current_weather.get("wind")

        return current_weather
