"""Camera support for the Skybell HD Doorbell."""
from __future__ import annotations

from datetime import timedelta
import logging

import requests
import voluptuous as vol

from homeassistant.components.camera import PLATFORM_SCHEMA, Camera
from homeassistant.const import CONF_MONITORED_CONDITIONS
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType

from . import DOMAIN as SKYBELL_DOMAIN, SkybellDevice

_LOGGER = logging.getLogger(__name__)

SCAN_INTERVAL = timedelta(seconds=90)

IMAGE_AVATAR = "avatar"
IMAGE_ACTIVITY = "activity"

CONF_ACTIVITY_NAME = "activity_name"
CONF_AVATAR_NAME = "avatar_name"

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
    {
        vol.Optional(CONF_MONITORED_CONDITIONS, default=[IMAGE_AVATAR]): vol.All(
            cv.ensure_list, [vol.In([IMAGE_AVATAR, IMAGE_ACTIVITY])]
        ),
        vol.Optional(CONF_ACTIVITY_NAME): cv.string,
        vol.Optional(CONF_AVATAR_NAME): cv.string,
    }
)


def setup_platform(
    hass: HomeAssistant,
    config: ConfigType,
    add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType | None = None,
) -> None:
    """Set up the platform for a Skybell device."""
    cond = config[CONF_MONITORED_CONDITIONS]
    names = {}
    names[IMAGE_ACTIVITY] = config.get(CONF_ACTIVITY_NAME)
    names[IMAGE_AVATAR] = config.get(CONF_AVATAR_NAME)
    skybell = hass.data[SKYBELL_DOMAIN]

    sensors = []
    for device in skybell.get_devices():
        for camera_type in cond:
            sensors.append(SkybellCamera(device, camera_type, names.get(camera_type)))

    add_entities(sensors, True)


class SkybellCamera(SkybellDevice, Camera):
    """A camera implementation for Skybell devices."""

    def __init__(self, device, camera_type, name=None):
        """Initialize a camera for a Skybell device."""
        self._type = camera_type
        SkybellDevice.__init__(self, device)
        Camera.__init__(self)
        if name is not None:
            self._name = f"{self._device.name} {name}"
        else:
            self._name = self._device.name
        self._url = None
        self._response = None

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

    @property
    def image_url(self):
        """Get the camera image url based on type."""
        if self._type == IMAGE_ACTIVITY:
            return self._device.activity_image
        return self._device.image

    def camera_image(
        self, width: int | None = None, height: int | None = None
    ) -> bytes | None:
        """Get the latest camera image."""
        super().update()

        if self._url != self.image_url:
            self._url = self.image_url

            try:
                self._response = requests.get(self._url, stream=True, timeout=10)
            except requests.HTTPError as err:
                _LOGGER.warning("Failed to get camera image: %s", err)
                self._response = None

        if not self._response:
            return None

        return self._response.content
