"""Tests for the Hyperion integration."""
from __future__ import annotations

import asyncio
import base64
from collections.abc import Awaitable
from typing import Callable
from unittest.mock import AsyncMock, Mock, patch

from aiohttp import web
import pytest

from homeassistant.components.camera import (
    DEFAULT_CONTENT_TYPE,
    DOMAIN as CAMERA_DOMAIN,
    async_get_image,
    async_get_mjpeg_stream,
)
from homeassistant.components.hyperion import get_hyperion_device_id
from homeassistant.components.hyperion.const import (
    DOMAIN,
    HYPERION_MANUFACTURER_NAME,
    HYPERION_MODEL_NAME,
    TYPE_HYPERION_CAMERA,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr, entity_registry as er

from . import (
    TEST_CONFIG_ENTRY_ID,
    TEST_INSTANCE,
    TEST_INSTANCE_1,
    TEST_SYSINFO_ID,
    async_call_registered_callback,
    create_mock_client,
    register_test_entity,
    setup_test_config_entry,
)

TEST_CAMERA_ENTITY_ID = "camera.test_instance_1"
TEST_IMAGE_DATA = "TEST DATA"
TEST_IMAGE_UPDATE = {
    "command": "ledcolors-imagestream-update",
    "result": {
        "image": "data:image/jpg;base64,"
        + base64.b64encode(TEST_IMAGE_DATA.encode()).decode("ascii"),
    },
    "success": True,
}


async def test_camera_setup(hass: HomeAssistant) -> None:
    """Test turning the light on."""
    client = create_mock_client()

    await setup_test_config_entry(hass, hyperion_client=client)

    # Verify switch is on (as per TEST_COMPONENTS above).
    entity_state = hass.states.get(TEST_CAMERA_ENTITY_ID)
    assert entity_state
    assert entity_state.state == "idle"


async def test_camera_image(hass: HomeAssistant) -> None:
    """Test retrieving a single camera image."""
    client = create_mock_client()
    client.async_send_image_stream_start = AsyncMock(return_value=True)
    client.async_send_image_stream_stop = AsyncMock(return_value=True)

    await setup_test_config_entry(hass, hyperion_client=client)

    get_image_coro = async_get_image(hass, TEST_CAMERA_ENTITY_ID)
    image_stream_update_coro = async_call_registered_callback(
        client, "ledcolors-imagestream-update", TEST_IMAGE_UPDATE
    )
    result = await asyncio.gather(get_image_coro, image_stream_update_coro)

    assert client.async_send_image_stream_start.called
    assert client.async_send_image_stream_stop.called
    assert result[0].content == TEST_IMAGE_DATA.encode()


async def test_camera_invalid_image(hass: HomeAssistant) -> None:
    """Test retrieving a single invalid camera image."""
    client = create_mock_client()
    client.async_send_image_stream_start = AsyncMock(return_value=True)
    client.async_send_image_stream_stop = AsyncMock(return_value=True)

    await setup_test_config_entry(hass, hyperion_client=client)

    get_image_coro = async_get_image(hass, TEST_CAMERA_ENTITY_ID, timeout=0)
    image_stream_update_coro = async_call_registered_callback(
        client, "ledcolors-imagestream-update", None
    )
    with pytest.raises(HomeAssistantError):
        await asyncio.gather(get_image_coro, image_stream_update_coro)