"""
A component which allows you to send data to an Influx database.

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/influxdb/
"""
import logging

import voluptuous as vol

from homeassistant.const import (
    EVENT_STATE_CHANGED, STATE_UNAVAILABLE, STATE_UNKNOWN, CONF_HOST,
    CONF_PORT, CONF_SSL, CONF_VERIFY_SSL, CONF_USERNAME, CONF_BLACKLIST,
    CONF_PASSWORD, CONF_WHITELIST)
from homeassistant.helpers import state as state_helper
import homeassistant.helpers.config_validation as cv

REQUIREMENTS = ['influxdb==3.0.0']

_LOGGER = logging.getLogger(__name__)

CONF_DB_NAME = 'database'
CONF_TAGS = 'tags'
CONF_DEFAULT_MEASUREMENT = 'default_measurement'

DEFAULT_DATABASE = 'home_assistant'
DEFAULT_HOST = 'localhost'
DEFAULT_PORT = 8086
DEFAULT_SSL = False
DEFAULT_VERIFY_SSL = False
DOMAIN = 'influxdb'
TIMEOUT = 5

CONFIG_SCHEMA = vol.Schema({
    DOMAIN: vol.Schema({
        vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string,
        vol.Inclusive(CONF_USERNAME, 'authentication'): cv.string,
        vol.Inclusive(CONF_PASSWORD, 'authentication'): cv.string,
        vol.Optional(CONF_BLACKLIST, default=[]):
            vol.All(cv.ensure_list, [cv.entity_id]),
        vol.Optional(CONF_DB_NAME, default=DEFAULT_DATABASE): cv.string,
        vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
        vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
        vol.Optional(CONF_DEFAULT_MEASUREMENT): cv.string,
        vol.Optional(CONF_TAGS, default={}):
            vol.Schema({cv.string: cv.string}),
        vol.Optional(CONF_WHITELIST, default=[]):
            vol.All(cv.ensure_list, [cv.entity_id]),
        vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean,
    }),
}, extra=vol.ALLOW_EXTRA)


def setup(hass, config):
    """Setup the InfluxDB component."""
    from influxdb import InfluxDBClient, exceptions

    conf = config[DOMAIN]

    host = conf.get(CONF_HOST)
    port = conf.get(CONF_PORT)
    database = conf.get(CONF_DB_NAME)
    username = conf.get(CONF_USERNAME)
    password = conf.get(CONF_PASSWORD)
    ssl = conf.get(CONF_SSL)
    verify_ssl = conf.get(CONF_VERIFY_SSL)
    blacklist = conf.get(CONF_BLACKLIST)
    whitelist = conf.get(CONF_WHITELIST)
    tags = conf.get(CONF_TAGS)
    default_measurement = conf.get(CONF_DEFAULT_MEASUREMENT)

    try:
        influx = InfluxDBClient(
            host=host, port=port, username=username, password=password,
            database=database, ssl=ssl, verify_ssl=verify_ssl,
            timeout=TIMEOUT)
        influx.query("select * from /.*/ LIMIT 1;")
    except exceptions.InfluxDBClientError as exc:
        _LOGGER.error("Database host is not accessible due to '%s', please "
                      "check your entries in the configuration file and that "
                      "the database exists and is READ/WRITE.", exc)
        return False

    def influx_event_listener(event):
        """Listen for new messages on the bus and sends them to Influx."""
        state = event.data.get('new_state')
        if state is None or state.state in (
                STATE_UNKNOWN, '', STATE_UNAVAILABLE) or \
                state.entity_id in blacklist:
            return

        try:
            if len(whitelist) > 0 and state.entity_id not in whitelist:
                return

            _state = state_helper.state_as_number(state)
        except ValueError:
            _state = state.state

        measurement = state.attributes.get('unit_of_measurement')
        if measurement in (None, ''):
            if default_measurement:
                measurement = default_measurement
            else:
                measurement = state.entity_id

        json_body = [
            {
                'measurement': measurement,
                'tags': {
                    'domain': state.domain,
                    'entity_id': state.object_id,
                },
                'time': event.time_fired,
                'fields': {
                    'value': _state,
                }
            }
        ]

        for key, value in state.attributes.items():
            if key != 'unit_of_measurement':
                if isinstance(value, (str, float, bool)) or \
                        key.endswith('_id'):
                    json_body[0]['fields'][key] = value
                elif isinstance(value, int):
                    # Prevent column data errors in influxDB.
                    json_body[0]['fields'][key] = float(value)

        json_body[0]['tags'].update(tags)

        try:
            influx.write_points(json_body)
        except exceptions.InfluxDBClientError:
            _LOGGER.exception('Error saving event "%s" to InfluxDB', json_body)

    hass.bus.listen(EVENT_STATE_CHANGED, influx_event_listener)

    return True

@@ -764,75 +764,8 @@
 nt'%0A
-DEFAULT_HOST = 'localhost'%0ADEFAULT_PORT = 8086%0ADEFAULT_SSL = False%0A
 DEFA
@@ -781,20 +781,19 @@
 Y_SSL = 
-Fals
+Tru
 e%0ADOMAIN
@@ -907,30 +907,8 @@
 HOST
-, default=DEFAULT_HOST
 ): c
@@ -1261,30 +1261,8 @@
 PORT
-, default=DEFAULT_PORT
 ): c
@@ -1302,29 +1302,8 @@
 _SSL
-, default=DEFAULT_SSL
 ): c
@@ -1836,116 +1836,328 @@
     
-host = conf.get(CONF_HOST)%0A    port = conf.get(CONF_PORT)%0A    database = conf.get(CONF_DB_NAME)%0A    
+kwargs = %7B%0A        'database': conf%5BCONF_DB_NAME%5D,%0A        'verify_ssl': conf%5BCONF_VERIFY_SSL%5D,%0A        'timeout': TIMEOUT%0A    %7D%0A%0A    if CONF_HOST in conf:%0A        kwargs%5B'host'%5D = conf%5BCONF_HOST%5D%0A%0A    if CONF_PORT in conf:%0A        kwargs%5B'port'%5D = conf%5BCONF_PORT%5D%0A%0A    if CONF_USERNAME in conf:%0A        kwargs%5B'
 username
  = c
@@ -2152,28 +2152,26 @@
 username
+'%5D
  = conf
-.get(
+%5B
 CONF_USE
@@ -2179,22 +2179,65 @@
 NAME
-)
+%5D%0A
 %0A    
+if CONF_PASSWORD in conf:%0A        kwargs%5B'
 password
  = c
@@ -2232,28 +2232,26 @@
 password
+'%5D
  = conf
-.get(
+%5B
 CONF_PAS
@@ -2259,81 +2259,75 @@
 WORD
-)
+%5D%0A
 %0A    
-ssl = conf.get(CONF_SSL)%0A    verify_
+if CONF_SSL in conf:%0A        kwargs%5B'
 ssl
+'%5D
  = conf
-.get(CONF_VERIFY
+%5BCONF
 _SSL
-)
+%5D%0A
 %0A   
@@ -2543,171 +2543,16 @@
 ent(
-%0A            host=host, port=port, username=username, password=password,%0A            database=database, ssl=ssl, verify_ssl=verify_ssl,%0A            timeout=TIMEOUT
+**kwargs
 )%0A  

Fix default auth influxdb (#4771)