# Source code for powerline.segments.common.wthr

    # vim:fileencoding=utf-8:noet
    from __future__ import (unicode_literals, division, absolute_import, print_function)

    import json
    from collections import namedtuple

    from powerline.lib.url import urllib_read, urllib_urlencode
    from powerline.lib.threaded import KwThreadedSegment
    from powerline.segments import with_docstring

    _WeatherKey = namedtuple('Key', 'location_query weather_api_key')

    # XXX Warning: module name must not be equal to the segment name as long as this
    # segment is imported into powerline.segments.common module.

    # Weather condition code descriptions available at
    # https://openweathermap.org/weather-conditions
    weather_conditions_codes = {
    	200: ('stormy',),
    	201: ('stormy',),
    	202: ('stormy',),
    	210: ('stormy',),
    	211: ('stormy',),
    	212: ('stormy',),
    	221: ('stormy',),
    	230: ('stormy',),
    	231: ('stormy',),
    	232: ('stormy',),
    	300: ('rainy',),
    	301: ('rainy',),
    	302: ('rainy',),
    	310: ('rainy',),
    	311: ('rainy',),
    	312: ('rainy',),
    	313: ('rainy',),
    	314: ('rainy',),
    	321: ('rainy',),
    	500: ('rainy',),
    	501: ('rainy',),
    	502: ('rainy',),
    	503: ('rainy',),
    	504: ('rainy',),
    	511: ('snowy',),
    	520: ('rainy',),
    	521: ('rainy',),
    	522: ('rainy',),
    	531: ('rainy',),
    	600: ('snowy',),
    	601: ('snowy',),
    	602: ('snowy',),
    	611: ('snowy',),
    	612: ('snowy',),
    	613: ('snowy',),
    	615: ('snowy',),
    	616: ('snowy',),
    	620: ('snowy',),
    	621: ('snowy',),
    	622: ('snowy',),
    	701: ('foggy',),
    	711: ('foggy',),
    	721: ('foggy',),
    	731: ('foggy',),
    	741: ('foggy',),
    	751: ('foggy',),
    	761: ('foggy',),
    	762: ('foggy',),
    	771: ('foggy',),
    	781: ('foggy',),
    	800: ('sunny',),
    	801: ('cloudy',),
    	802: ('cloudy',),
    	803: ('cloudy',),
    	804: ('cloudy',),
    }

    weather_conditions_icons = {
    	'day':           'DAY',
    	'blustery':      'WIND',
    	'rainy':         'RAIN',
    	'cloudy':        'CLOUDS',
    	'snowy':         'SNOW',
    	'stormy':        'STORM',
    	'foggy':         'FOG',
    	'sunny':         'SUN',
    	'night':         'NIGHT',
    	'windy':         'WINDY',
    	'not_available': 'NA',
    	'unknown':       'UKN',
    }

    temp_conversions = {
    	'C': lambda temp: temp - 273.15,
    	'F': lambda temp: (temp * 9 / 5) - 459.67,
    	'K': lambda temp: temp,
    }

    # Note: there are also unicode characters for units: ℃, ℉ and  K
    temp_units = {
    	'C': '°C',
    	'F': '°F',
    	'K': 'K',
    }

    class WeatherSegment(KwThreadedSegment):
    	interval = 600
    	default_location = None
    	location_urls = {}
    	weather_api_key = "fbc9549d91a5e4b26c15be0dbdac3460"

    	@staticmethod
    	def key(location_query=None, **kwargs):
    		try:
    			weather_api_key = kwargs["weather_api_key"]
    		except KeyError:
    			weather_api_key = WeatherSegment.weather_api_key
    		return _WeatherKey(location_query, weather_api_key)

    	def get_request_url(self, weather_key):
    		try:
    			return self.location_urls[weather_key]
    		except KeyError:
    			query_data = {
    				"appid": weather_key.weather_api_key
    			}
    			location_query = weather_key.location_query
    			if location_query is None:
    				location_data = json.loads(urllib_read('https://freegeoip.app/json/'))
    				query_data["lat"] = location_data["latitude"]
    				query_data["lon"] = location_data["longitude"]
    			else:
    				query_data["q"] = location_query
    			self.location_urls[location_query] = url = (
    				"https://api.openweathermap.org/data/2.5/weather?" +
    				urllib_urlencode(query_data))
    			return url

    	def compute_state(self, weather_key):
    		url = self.get_request_url(weather_key)
    		raw_response = urllib_read(url)
    		if not raw_response:
    			self.error('Failed to get response')
    			return None

    		response = json.loads(raw_response)
    		try:
    			condition = response['weather'][0]
    			condition_code = int(condition['id'])
    			temp = float(response['main']['temp'])
    		except (KeyError, ValueError):
    			self.exception('OpenWeatherMap returned malformed or unexpected response: {0}', repr(raw_response))
    			return None

    		try:
    			icon_names = weather_conditions_codes[condition_code]
    		except IndexError:
    			icon_names = ('unknown',)
    			self.error('Unknown condition code: {0}', condition_code)

    		return (temp, icon_names)

    	def render_one(self, weather, icons=None, unit='C', temp_format=None, temp_coldest=-30, temp_hottest=40, **kwargs):
    		if not weather:
    			return None

    		temp, icon_names = weather

    		for icon_name in icon_names:
    			if icons:
    				if icon_name in icons:
    					icon = icons[icon_name]
    					break
    		else:
    			icon = weather_conditions_icons[icon_names[-1]]

    		temp_format = temp_format or ('{temp:.0f}' + temp_units[unit])
    		converted_temp = temp_conversions[unit](temp)
    		if converted_temp <= temp_coldest:
    			gradient_level = 0
    		elif converted_temp >= temp_hottest:
    			gradient_level = 100
    		else:
    			gradient_level = (converted_temp - temp_coldest) * 100.0 / (temp_hottest - temp_coldest)
    		groups = ['weather_condition_' + icon_name for icon_name in icon_names] + ['weather_conditions', 'weather']
    		return [
    			{
    				'contents': icon + ' ',
    				'highlight_groups': groups,
    				'divider_highlight_group': 'background:divider',
    			},
    			{
    				'contents': temp_format.format(temp=converted_temp),
    				'highlight_groups': ['weather_temp_gradient', 'weather_temp', 'weather'],
    				'divider_highlight_group': 'background:divider',
    				'gradient_level': gradient_level,
    			},
    		]

    weather = with_docstring(WeatherSegment(),
    '''Return weather from OpenWeatherMaps.

    Uses GeoIP lookup from https://freegeoip.app to automatically determine
    your current location. This should be changed if you’re in a VPN or if your
    IP address is registered at another location.

    Returns a list of colorized icon and temperature segments depending on
    weather conditions.

    :param str unit:
    	temperature unit, can be one of ``F``, ``C`` or ``K``
    :param str location_query:
    	location query for your current location, e.g. ``oslo, norway``
    :param dict icons:
    	dict for overriding default icons, e.g. ``{'heavy_snow' : u'❆'}``
    :param str temp_format:
    	format string, receives ``temp`` as an argument. Should also hold unit.
    :param float temp_coldest:
    	coldest temperature. Any temperature below it will have gradient level equal
    	to zero.
    :param float temp_hottest:
    	hottest temperature. Any temperature above it will have gradient level equal
    	to 100. Temperatures between ``temp_coldest`` and ``temp_hottest`` receive
    	gradient level that indicates relative position in this interval
    	(``100 * (cur-coldest) / (hottest-coldest)``).

    Divider highlight group used: ``background:divider``.

    Highlight groups used: ``weather_conditions`` or ``weather``, ``weather_temp_gradient`` (gradient) or ``weather``.
    Also uses ``weather_conditions_{condition}`` for all weather conditions supported by OpenWeatherMap.
    ''')