"""Contains the shared Coordinator for Starlink systems."""
from __future__ import annotations

from dataclasses import dataclass
from datetime import timedelta
import logging

import async_timeout
from starlink_grpc import (
    AlertDict,
    ChannelContext,
    GrpcError,
    ObstructionDict,
    StatusDict,
    reboot,
    set_stow_state,
    status_data,
)

from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

_LOGGER = logging.getLogger(__name__)


@dataclass
class StarlinkData:
    """Contains data pulled from the Starlink system."""

    status: StatusDict
    obstruction: ObstructionDict
    alert: AlertDict


class StarlinkUpdateCoordinator(DataUpdateCoordinator[StarlinkData]):
    """Coordinates updates between all Starlink sensors defined in this file."""

    def __init__(self, hass: HomeAssistant, name: str, url: str) -> None:
        """Initialize an UpdateCoordinator for a group of sensors."""
        self.channel_context = ChannelContext(target=url)

        super().__init__(
            hass,
            _LOGGER,
            name=name,
            update_interval=timedelta(seconds=5),
        )

    async def _async_update_data(self) -> StarlinkData:
        async with async_timeout.timeout(4):
            try:
                status = await self.hass.async_add_executor_job(
                    status_data, self.channel_context
                )
                return StarlinkData(*status)
            except GrpcError as exc:
                raise UpdateFailed from exc

    async def async_stow_starlink(self, stow: bool):
        """Set whether Starlink system tied to this coordinator should be stowed."""
        async with async_timeout.timeout(4):
            try:
                await self.hass.async_add_executor_job(
                    set_stow_state, not stow, self.channel_context
                )
            except GrpcError as exc:
                raise HomeAssistantError from exc

    async def async_reboot_starlink(self):
        """Reboot the Starlink system tied to this coordinator."""
        async with async_timeout.timeout(4):
            try:
                await self.hass.async_add_executor_job(reboot, self.channel_context)
            except GrpcError as exc:
                raise HomeAssistantError from exc
