from datetime import datetime, timedelta, timezone
import itertools
import json
import os
import urllib.error
import urllib.parse
import urllib.request

class DarkSkyAPI:

    def __init__(self, apikey=None, gps=None, opts={"lang": "fr", "units": "metric"}):
        self.apikey = apikey or os.environ["WEATHERAPIKEY"]
        self.baseurl = "https://api.openweathermap.org/data/3.0/onecall"
        self.default_gps = gps or ("GPS" in os.environ and os.environ["GPS"]) or "48.8127,2.3437"
        self.opts = opts

        self._cached_file = ".darksky-%s.cache"


    def get_weather(self, gps=None):
        if gps is None:
            gps = self.default_gps

        # Read the mod time
        statinfo = None
        try:
            statinfo = os.stat(self._cached_file % gps)
        except:
            pass

        if statinfo is None or datetime.fromtimestamp(statinfo.st_mtime, tz=timezone.utc) + timedelta(hours=1) < datetime.now(tz=timezone.utc):
            # Do the request and save it
            try:
                (lat,lon) = gps.split(",")
                with urllib.request.urlopen(self.baseurl + "?appid=" + str(self.apikey) + "&lat=" + str(lat) + "&lon=" + str(lon) + "&" + ("&".join([opt+"="+self.opts[opt] for opt in self.opts]))) as f:
                    with open(self._cached_file % gps, 'wb') as fd:
                        fd.write(f.read())
            except ConnectionResetError:
                pass
            #except urllib.error.URLError:
            #    pass


        # Retrieve cached data
        res = {}
        with open(self._cached_file % gps) as f:
            res = json.load(f)

        return res


    def get_icon(icon, night=False, current=False):
        # 200: Thunderstorm
        if icon < 300:
            if icon == 200 or icon == 201 or icon == 202:
                if not night:
                    return "wi-day-thunderstorm.png"
                else:
                    return "wi-night-thunderstorm.png"
            elif icon == 210 or icon == 211:
                return "wi-thunderstorm.png"
            elif icon == 212 or icon == 221:
                return "wi-lightning.png"
            elif icon == 230 or icon == 231 or icon == 232:
                if not night:
                    return "wi-day-storm-showers.png"
                else:
                    return "wi-night-storm-showers.png"
            else:
                return "wi-thunderstorm.png"

        # 300: Drizzle
        elif icon < 400:
            if icon < 311:
                if not night:
                    return "wi-day-showers.png"
                else:
                    return "wi-night-showers.png"
            else:
                return "wi-showers.png"

        # 500: Rain
        elif icon < 600:
            if icon == 500:
                if not night:
                    return "wi-day-rain.png"
                else:
                    return "wi-night-rain.png"
            if icon < 510:
                return "wi-rain.png"
            elif icon < 520:
                if current:
                    return "wi-hail.png"
                elif not night:
                    return "wi-day-hail.png"
                else:
                    return "wi-night-hail.png"
            elif icon == 520:
                if not night:
                    return "wi-day-showers.png"
                else:
                    return "wi-night-showers.png"
            elif icon > 520:
                return "wi-showers.png"
            else:
                return "wi-rain.png"

        # 600: Snow
        elif icon < 700:
            if icon == 600:
                if not night:
                    return "wi-day-snow.png"
                else:
                    return "wi-night-alt-snow.png"
            elif icon < 610:
                return "wi-snow.png"
            elif icon < 620:
                if current:
                    return "wi-sleet.png"
                if not night:
                    return "wi-day-sleet.png"
                else:
                    return "wi-night-alt-sleet.png"
            elif icon == 620:
                if not night:
                    return "wi-day-snow-wind.png"
                else:
                    return "wi-night-snow-wind.png"
            elif icon < 630:
                return "wi-snow-wind.png"
            else:
                return "wi-snow.png"

        # Atmosphere
        elif icon < 800:
            if icon == 701:
                if not night:
                    return "wi-day-haze.png"
                else:
                    return "wi-night-fog.png"
            elif icon < 720:
                return "wi-smoke.png"
            elif icon < 730:
                if not night:
                    return "wi-day-haze.png"
                else:
                    return "wi-night-fog.png"
            elif icon < 740:
                return "wi-dust.png"
            elif icon < 750:
                if not night:
                    return "wi-day-fog.png"
                else:
                    return "wi-night-fog.png"
            elif icon == 751:
                return "wi-sandstorm.png"
            elif icon < 762:
                return "wi-dust.png"
            elif icon == 762:
                return "wi-volcano.png"
            elif icon == 771:
                return "wi-strong-wind.png"
            elif icon == 781:
                return "wi-tornado.png"

        # 800: Clear
        if icon == 800:
            if not night:
                return "wi-day-sunny.png"
            else:
                return "wi-night-clear.png"

        # 800: Clouds
        elif icon == 801:
            if not night:
                return "wi-day-sunny-overcast.png"
            else:
                return "wi-night-alt-partly-cloudy.png"
        elif icon == 802:
            if not night:
                return "wi-day-cloudy.png"
            else:
                return "wi-night-alt-cloudy.png"
        elif icon == 804:
            return "wi-cloudy.png"
        elif icon < 900:
            return "wi-cloud.png"

        return "wi-alien.png"


    def get_moon_icon(self, day=0):
        thisdayweather = list(itertools.islice(self.get_daily(), 1))[0]
        moon_phase = thisdayweather["moon_phase"]

        if moon_phase < 0.035:
            return "wi-moon-alt-new.png"
        elif moon_phase < 0.071:
            return "wi-moon-alt-waxing-crescent-1.png"
        elif moon_phase < 0.107:
            return "wi-moon-alt-waxing-crescent-2.png"
        elif moon_phase < 0.142:
            return "wi-moon-alt-waxing-crescent-3.png"
        elif moon_phase < 0.178:
            return "wi-moon-alt-waxing-crescent-4.png"
        elif moon_phase < 0.214:
            return "wi-moon-alt-waxing-crescent-5.png"
        elif moon_phase < 0.25:
            return "wi-moon-alt-waxing-crescent-6.png"
        elif moon_phase < 0.285:
            return "wi-moon-alt-first-quarter.png"
        elif moon_phase < 0.321:
            return "wi-moon-alt-waxing-gibbous-1.png"
        elif moon_phase < 0.357:
            return "wi-moon-alt-waxing-gibbous-2.png"
        elif moon_phase < 0.392:
            return "wi-moon-alt-waxing-gibbous-3.png"
        elif moon_phase < 0.428:
            return "wi-moon-alt-waxing-gibbous-4.png"
        elif moon_phase < 0.464:
            return "wi-moon-alt-waxing-gibbous-5.png"
        elif moon_phase < 0.5:
            return "wi-moon-alt-waxing-gibbous-6.png"
        elif moon_phase < 0.535:
            return "wi-moon-alt-full.png"
        elif moon_phase < 0.571:
            return "wi-moon-alt-waning-gibbous-1.png"
        elif moon_phase < 0.607:
            return "wi-moon-alt-waning-gibbous-2.png"
        elif moon_phase < 0.642:
            return "wi-moon-alt-waning-gibbous-3.png"
        elif moon_phase < 0.678:
            return "wi-moon-alt-waning-gibbous-4.png"
        elif moon_phase < 0.714:
            return "wi-moon-alt-waning-gibbous-5.png"
        elif moon_phase < 0.75:
            return "wi-moon-alt-waning-gibbous-6.png"
        elif moon_phase < 0.785:
            return "wi-moon-alt-third-quarter.png"
        elif moon_phase < 0.821:
            return "wi-moon-alt-waning-crescent-1.png"
        elif moon_phase < 0.857:
            return "wi-moon-alt-waning-crescent-2.png"
        elif moon_phase < 0.892:
            return "wi-moon-alt-waning-crescent-3.png"
        elif moon_phase < 0.928:
            return "wi-moon-alt-waning-crescent-4.png"
        elif moon_phase < 0.964:
            return "wi-moon-alt-waning-crescent-5.png"
        else:
            return "wi-moon-alt-waning-crescent-6.png"


    def get_currently(self, *args, **kwargs):
        cur = self.get_weather(*args, **kwargs)["current"]
        cur["is_day"] = True
        return cur


    def get_hourly(self, *args, **kwargs):
        return self.get_weather(*args, **kwargs)["hourly"]


    def get_daily(self, *args, **kwargs):
        for d in self.get_weather(*args, **kwargs)["daily"]:
            d["date"] = datetime.fromtimestamp(d["dt"])
            yield d

    def has_alerts(self, *args, **kwargs):
        return "alerts" in self.get_weather(*args, **kwargs) and len(self.get_weather(*args, **kwargs)["alerts"]) > 0

    def get_alerts(self, *args, **kwargs):
        w = self.get_weather(*args, **kwargs)
        if "alerts" in w:
            return w["alerts"]
        return []

    def read_timestamp(self, timestamp, *args, **kwargs):
        wth = self.get_weather(*args, **kwargs)

        tz = timezone(timedelta(seconds=wth["timezone_offset"]), wth["timezone"])
        return datetime.fromtimestamp(timestamp, tz=tz)


WeatherAPI = DarkSkyAPI

if __name__ == '__main__':
    dsa = DarkSkyAPI()
    print(dsa.get_currently())
