"""Common Met Office Data class used by both sensor and entity."""

import logging

import datapoint

from .const import MODE_3HOURLY

_LOGGER = logging.getLogger(__name__)


class MetOfficeData:
    """Get current and forecast data from Datapoint.

    Please note that the 'datapoint' library is not asyncio-friendly, so some
    calls have had to be wrapped with the standard hassio helper
    async_add_executor_job.
    """

    def __init__(self, hass, api_key, latitude, longitude):
        """Initialize the data object."""
        self._hass = hass
        self._datapoint = datapoint.connection(api_key=api_key)
        self._site = None

        # Public attributes
        self.latitude = latitude
        self.longitude = longitude

        # Holds the current data from the Met Office
        self.site_id = None
        self.site_name = None
        self.now = None

    async def async_update_site(self):
        """Async wrapper for getting the DataPoint site."""
        return await self._hass.async_add_executor_job(self._update_site)

    def _update_site(self):
        """Return the nearest DataPoint Site to the held latitude/longitude."""
        try:
            new_site = self._datapoint.get_nearest_forecast_site(
                latitude=self.latitude, longitude=self.longitude
            )
            if self._site is None or self._site.id != new_site.id:
                self._site = new_site
                self.now = None

            self.site_id = self._site.id
            self.site_name = self._site.name

        except datapoint.exceptions.APIException as err:
            _LOGGER.error("Received error from Met Office Datapoint: %s", err)
            self._site = None
            self.site_id = None
            self.site_name = None
            self.now = None

        return self._site

    async def async_update(self):
        """Async wrapper for update method."""
        return await self._hass.async_add_executor_job(self._update)

    def _update(self):
        """Get the latest data from DataPoint."""
        if self._site is None:
            _LOGGER.error("No Met Office forecast site held, check logs for problems")
            return

        try:
            forecast = self._datapoint.get_forecast_for_site(
                self._site.id, MODE_3HOURLY
            )
            self.now = forecast.now()
        except (ValueError, datapoint.exceptions.APIException) as err:
            _LOGGER.error("Check Met Office connection: %s", err.args)
            self.now = None