'''
---------------------------------------------------------
NWS Alerts
---------------------------------------------------------
VERSION: 0.0.2
Forum: https://community.home-assistant.io/t/severe-weather-alerts-from-the-us-national-weather-service/71853

API Documentation
---------------------------------------------------------
https://www.weather.gov/documentation/services-web-api
https://forecast-v3.weather.gov/documentation
---------------------------------------------------------
'''

import requests
import logging
import voluptuous as vol
from datetime import timedelta
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import CONF_NAME, ATTR_ATTRIBUTION
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle


API_ENDPOINT = 'https://api.weather.gov'
USER_AGENT = 'Home Assistant'
DEFAULT_ICON = 'mdi:alert'
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1)
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'NWS Alerts'
CONF_ZONE_ID = 'zone_id'
ZONE_ID = ''

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Required(CONF_ZONE_ID): cv.string,
    vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
})


def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup the sensor platform."""
    name = config.get(CONF_NAME, DEFAULT_NAME)
    zone_id = config.get(CONF_ZONE_ID)
    add_devices([NWSAlertSensor(name, zone_id)])


class NWSAlertSensor(Entity):
    """Representation of a Sensor."""

    def __init__(self, name, zone_id):
        """Initialize the sensor."""
        self._name = name
        self._icon = DEFAULT_ICON
        self._state = 0
        self._event = None
        self._display_desc = None
        self._spoken_desc = None
        self._zone_id = zone_id.replace(' ', '')
        self.update()

    @property
    def name(self):
        """Return the name of the sensor."""
        return self._name

    @property
    def icon(self):
        """Return the icon to use in the frontend, if any."""
        return self._icon

    @property
    def state(self):
        """Return the state of the sensor."""
        return self._state

    @property
    def device_state_attributes(self):
        """Return the state message."""
        attributes = {"title": self._event,
                      "display_desc": self._display_desc,
                      "spoken_desc": self._spoken_desc
                      }

        return attributes

    @Throttle(MIN_TIME_BETWEEN_UPDATES)
    def update(self):
        """Fetch new state data for the sensor.
        This is the only method that should fetch new data for Home Assistant.
        """
        values = self.get_state()
        self._state = values['state']
        self._event = values['event']
        self._display_desc = values['display_desc']
        self._spoken_desc = values['spoken_desc']

    def get_state(self):
        values = {'state': 0,
                  'event': None,
                  'display_desc': None,
                  'spoken_desc': None
                  }

        headers = {'User-Agent': USER_AGENT,
                   'Accept': 'application/ld+json'
                   }

        url = '%s/alerts/active/count' % API_ENDPOINT
        r = requests.get(url, headers=headers)
        _LOGGER.debug("getting state, %s", url)
        if r.status_code == 200:
            if 'zones' in r.json():
                for zone in self._zone_id.split(','):
                    if zone in r.json()['zones']:
                        values = self.get_alerts()
                        break

        return values

    def get_alerts(self):
        values = {'state': 0,
                  'event': None,
                  'display_desc': None,
                  'spoken_desc': None
                  }

        headers = {'User-Agent': USER_AGENT,
                   'Accept': 'application/geo+json'
                   }
        url = '%s/alerts/active?zone=%s' % (API_ENDPOINT, self._zone_id)
        r = requests.get(url, headers=headers)
        _LOGGER.debug("getting alert, %s", url)
        if r.status_code == 200:
            events = []
            headlines = []
            display_desc = ''
            spoken_desc = ''
            features = r.json()['features']
            for alert in features:
                event = alert['properties']['event']
                if 'NWSheadline' in alert['properties']['parameters']:
                    headline = alert['properties']['parameters']['NWSheadline'][0]
                else:
                    headline = event

                description = alert['properties']['description']
                instruction = alert['properties']['instruction']

                if event in events:
                    continue

                events.append(event)
                headlines.append(headline)

                if display_desc != '':
                    display_desc += '\n\n'

                display_desc += '<b>%s</b>\n%s\n%s\n%s' % (event, headline, description, instruction)

            if headlines:
                num_headlines = len(headlines)
                i = 0
                for headline in headlines:
                    i += 1
                    if spoken_desc != '':
                        if i == num_headlines:
                            spoken_desc += ' and a '
                        else:
                            spoken_desc += ', a '

                    spoken_desc += headline

            if len(events) > 0:
                event_str = ''
                for item in events:
                    if event_str != '':
                        event_str += ' - '
                    event_str += item

                values['state'] = len(events)
                values['event'] = event_str
                values['display_desc'] = display_desc
                values['spoken_desc'] = spoken_desc

        return values