"""Support for HomematicIP Cloud alarm control panel."""
import logging

from homematicip.aio.group import AsyncSecurityZoneGroup
from homematicip.aio.home import AsyncHome
from homematicip.base.enums import WindowState

from homeassistant.components.alarm_control_panel import AlarmControlPanel
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
    STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
    STATE_ALARM_TRIGGERED)
from homeassistant.core import HomeAssistant

from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID

_LOGGER = logging.getLogger(__name__)

CONST_ALARM_CONTROL_PANEL_NAME = 'HmIP Alarm Control Panel'


async def async_setup_platform(
        hass, config, async_add_entities, discovery_info=None):
    """Set up the HomematicIP Cloud alarm control devices."""
    pass


async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry,
                            async_add_entities) -> None:
    """Set up the HomematicIP alrm control panel from a config entry."""
    home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home
    devices = []
    security_zones = []
    for group in home.groups:
        if isinstance(group, AsyncSecurityZoneGroup):
            security_zones.append(group)

    if security_zones:
        devices.append(HomematicipAlarmControlPanel(home, security_zones))

    if devices:
        async_add_entities(devices)


class HomematicipAlarmControlPanel(AlarmControlPanel):
    """Representation of an alarm control panel."""

    def __init__(self, home: AsyncHome, security_zones) -> None:
        """Initialize the alarm control panel."""
        self._home = home
        self.alarm_state = STATE_ALARM_DISARMED

        for security_zone in security_zones:
            if security_zone.label == 'INTERNAL':
                self._internal_alarm_zone = security_zone
            else:
                self._external_alarm_zone = security_zone

    @property
    def state(self) -> str:
        """Return the state of the device."""
        activation_state = self._home.get_security_zones_activation()
        # check arm_away
        if activation_state == (True, True):
            if self._internal_alarm_zone_state or \
                    self._external_alarm_zone_state:
                return STATE_ALARM_TRIGGERED
            return STATE_ALARM_ARMED_AWAY
        # check arm_home
        if activation_state == (False, True):
            if self._external_alarm_zone_state:
                return STATE_ALARM_TRIGGERED
            return STATE_ALARM_ARMED_HOME

        return STATE_ALARM_DISARMED

    @property
    def _internal_alarm_zone_state(self) -> bool:
        return _get_zone_alarm_state(self._internal_alarm_zone)

    @property
    def _external_alarm_zone_state(self) -> bool:
        """Return the state of the device."""
        return _get_zone_alarm_state(self._external_alarm_zone)

    async def async_alarm_disarm(self, code=None):
        """Send disarm command."""
        await self._home.set_security_zones_activation(False, False)

    async def async_alarm_arm_home(self, code=None):
        """Send arm home command."""
        await self._home.set_security_zones_activation(False, True)

    async def async_alarm_arm_away(self, code=None):
        """Send arm away command."""
        await self._home.set_security_zones_activation(True, True)

    async def async_added_to_hass(self):
        """Register callbacks."""
        self._internal_alarm_zone.on_update(self._async_device_changed)
        self._external_alarm_zone.on_update(self._async_device_changed)

    def _async_device_changed(self, *args, **kwargs):
        """Handle device state changes."""
        _LOGGER.debug("Event %s (%s)", self.name,
                      CONST_ALARM_CONTROL_PANEL_NAME)
        self.async_schedule_update_ha_state()

    @property
    def name(self) -> str:
        """Return the name of the generic device."""
        name = CONST_ALARM_CONTROL_PANEL_NAME
        if self._home.name:
            name = "{} {}".format(self._home.name, name)
        return name

    @property
    def should_poll(self) -> bool:
        """No polling needed."""
        return False

    @property
    def available(self) -> bool:
        """Device available."""
        return not self._internal_alarm_zone.unreach or \
            not self._external_alarm_zone.unreach

    @property
    def unique_id(self) -> str:
        """Return a unique ID."""
        return "{}_{}".format(self.__class__.__name__, self._home.id)


def _get_zone_alarm_state(security_zone) -> bool:
    if security_zone.active:
        if (security_zone.sabotage or
                security_zone.motionDetected or
                security_zone.presenceDetected or
                security_zone.windowState == WindowState.OPEN or
                security_zone.windowState == WindowState.TILTED):
            return True

    return False
