"""
Core components of Home Assistant.

Home Assistant is a Home Automation framework for observing the state
of entities and react to changes.
"""

import enum
import functools as ft
import logging
import os
import signal
import threading
import time
from types import MappingProxyType

import voluptuous as vol

import homeassistant.helpers.temperature as temp_helper
import homeassistant.util as util
import homeassistant.util.dt as dt_util
import homeassistant.util.location as location
from homeassistant.config import get_default_config_dir
from homeassistant.const import (
    ATTR_DOMAIN, ATTR_FRIENDLY_NAME, ATTR_NOW, ATTR_SERVICE,
    ATTR_SERVICE_CALL_ID, ATTR_SERVICE_DATA, EVENT_CALL_SERVICE,
    EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
    EVENT_SERVICE_EXECUTED, EVENT_SERVICE_REGISTERED, EVENT_STATE_CHANGED,
    EVENT_TIME_CHANGED, MATCH_ALL, RESTART_EXIT_CODE,
    SERVICE_HOMEASSISTANT_RESTART, SERVICE_HOMEASSISTANT_STOP, TEMP_CELSIUS,
    TEMP_FAHRENHEIT, __version__)
from homeassistant.exceptions import (
    HomeAssistantError, InvalidEntityFormatError)
from homeassistant.helpers.entity import split_entity_id, valid_entity_id

DOMAIN = "homeassistant"

# How often time_changed event should fire
TIMER_INTERVAL = 1  # seconds

# How long we wait for the result of a service call
SERVICE_CALL_LIMIT = 10  # seconds

# Define number of MINIMUM worker threads.
# During bootstrap of HA (see bootstrap._setup_component()) worker threads
# will be added for each component that polls devices.
MIN_WORKER_THREAD = 2

_LOGGER = logging.getLogger(__name__)


class CoreState(enum.Enum):
    """Represent the current state of Home Assistant."""

    not_running = "NOT_RUNNING"
    starting = "STARTING"
    running = "RUNNING"
    stopping = "STOPPING"

    def __str__(self):
        """Return the event."""
        return self.value


class HomeAssistant(object):
    """Root object of the Home Assistant home automation."""

    def __init__(self):
        """Initialize new Home Assistant object."""
        self.pool = pool = create_worker_pool()