"""Support for Neato botvac connected vacuum cleaners."""
import logging
from datetime import timedelta
from urllib.error import HTTPError

import voluptuous as vol

import homeassistant.helpers.config_validation as cv
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.helpers import discovery
from homeassistant.util import Throttle

_LOGGER = logging.getLogger(__name__)

CONF_VENDOR = "vendor"
DOMAIN = "neato"
NEATO_ROBOTS = "neato_robots"
NEATO_LOGIN = "neato_login"
NEATO_MAP_DATA = "neato_map_data"
NEATO_PERSISTENT_MAPS = "neato_persistent_maps"

CONFIG_SCHEMA = vol.Schema(
    {
        DOMAIN: vol.Schema(
            {
                vol.Required(CONF_USERNAME): cv.string,
                vol.Required(CONF_PASSWORD): cv.string,
                vol.Optional(CONF_VENDOR, default="neato"): vol.In(
                    ["neato", "vorwerk"]
                ),
            }
        )
    },
    extra=vol.ALLOW_EXTRA,
)

MODE = {1: "Eco", 2: "Turbo"}

ACTION = {
    0: "Invalid",
    1: "House Cleaning",
    2: "Spot Cleaning",
    3: "Manual Cleaning",
    4: "Docking",
    5: "User Menu Active",
    6: "Suspended Cleaning",
    7: "Updating",
    8: "Copying logs",
    9: "Recovering Location",
    10: "IEC test",
    11: "Map cleaning",
    12: "Exploring map (creating a persistent map)",
    13: "Acquiring Persistent Map IDs",
    14: "Creating & Uploading Map",
    15: "Suspended Exploration",
}

ERRORS = {
    "ui_error_battery_battundervoltlithiumsafety": "Replace battery",
    "ui_error_battery_critical": "Replace battery",
    "ui_error_battery_invalidsensor": "Replace battery",
    "ui_error_battery_lithiumadapterfailure": "Replace battery",
    "ui_error_battery_mismatch": "Replace battery",
    "ui_error_battery_nothermistor": "Replace battery",
    "ui_error_battery_overtemp": "Replace battery",
    "ui_error_battery_overvolt": "Replace battery",
    "ui_error_battery_undercurrent": "Replace battery",
    "ui_error_battery_undertemp": "Replace battery",
    "ui_error_battery_undervolt": "Replace battery",
    "ui_error_battery_unplugged": "Replace battery",
    "ui_error_brush_stuck": "Brush stuck",
    "ui_error_brush_overloaded": "Brush overloaded",
    "ui_error_bumper_stuck": "Bumper stuck",
    "ui_error_check_battery_switch": "Check battery",
    "ui_error_corrupt_scb": "Call customer service corrupt board",
    "ui_error_deck_debris": "Deck debris",
    "ui_error_dflt_app": "Check Neato app",
    "ui_error_disconnect_chrg_cable": "Disconnected charge cable",
    "ui_error_disconnect_usb_cable": "Disconnected USB cable",
    "ui_error_dust_bin_missing": "Dust bin missing",
    "ui_error_dust_bin_full": "Dust bin full",
    "ui_error_dust_bin_emptied": "Dust bin emptied",
    "ui_error_hardware_failure": "Hardware failure",
    "ui_error_ldrop_stuck": "Clear my path",
    "ui_error_lds_jammed": "Clear my path",
    "ui_error_lds_bad_packets": "Check Neato app",
    "ui_error_lds_disconnected": "Check Neato app",
    "ui_error_lds_missed_packets": "Check Neato app",
    "ui_error_lwheel_stuck": "Clear my path",
    "ui_error_navigation_backdrop_frontbump": "Clear my path",
    "ui_error_navigation_backdrop_leftbump": "Clear my path",
    "ui_error_navigation_backdrop_wheelextended": "Clear my path",
    "ui_error_navigation_noprogress": "Clear my path",
    "ui_error_navigation_origin_unclean": "Clear my path",
    "ui_error_navigation_pathproblems": "Cannot return to base",
    "ui_error_navigation_pinkycommsfail": "Clear my path",
    "ui_error_navigation_falling": "Clear my path",
    "ui_error_navigation_noexitstogo": "Clear my path",
    "ui_error_navigation_nomotioncommands": "Clear my path",
    "ui_error_navigation_rightdrop_leftbump": "Clear my path",
    "ui_error_navigation_undockingfailed": "Clear my path",
    "ui_error_picked_up": "Picked up",
    "ui_error_qa_fail": "Check Neato app",
    "ui_error_rdrop_stuck": "Clear my path",
    "ui_error_reconnect_failed": "Reconnect failed",
    "ui_error_rwheel_stuck": "Clear my path",
    "ui_error_stuck": "Stuck!",
    "ui_error_unable_to_return_to_base": "Unable to return to base",
    "ui_error_unable_to_see": "Clean vacuum sensors",
    "ui_error_vacuum_slip": "Clear my path",
    "ui_error_vacuum_stuck": "Clear my path",
    "ui_error_warning": "Error check app",
    "batt_base_connect_fail": "Battery failed to connect to base",
    "batt_base_no_power": "Battery base has no power",
    "batt_low": "Battery low",
    "batt_on_base": "Battery on base",
    "clean_tilt_on_start": "Clean the tilt on start",
    "dustbin_full": "Dust bin full",
    "dustbin_missing": "Dust bin missing",
    "gen_picked_up": "Picked up",
    "hw_fail": "Hardware failure",
    "hw_tof_sensor_sensor": "Hardware sensor disconnected",
    "lds_bad_packets": "Bad packets",
    "lds_deck_debris": "Debris on deck",
    "lds_disconnected": "Disconnected",
    "lds_jammed": "Jammed",
    "lds_missed_packets": "Missed packets",
    "maint_brush_stuck": "Brush stuck",
    "maint_brush_overload": "Brush overloaded",
    "maint_bumper_stuck": "Bumper stuck",
    "maint_customer_support_qa": "Contact customer support",
    "maint_vacuum_stuck": "Vacuum is stuck",
    "maint_vacuum_slip": "Vacuum is stuck",
    "maint_left_drop_stuck": "Vacuum is stuck",
    "maint_left_wheel_stuck": "Vacuum is stuck",
    "maint_right_drop_stuck": "Vacuum is stuck",
    "maint_right_wheel_stuck": "Vacuum is stuck",
    "not_on_charge_base": "Not on the charge base",
    "nav_robot_falling": "Clear my path",
    "nav_no_path": "Clear my path",
    "nav_path_problem": "Clear my path",
    "nav_backdrop_frontbump": "Clear my path",
    "nav_backdrop_leftbump": "Clear my path",
    "nav_backdrop_wheelextended": "Clear my path",
    "nav_mag_sensor": "Clear my path",
    "nav_no_exit": "Clear my path",
    "nav_no_movement": "Clear my path",
    "nav_rightdrop_leftbump": "Clear my path",
    "nav_undocking_failed": "Clear my path",
}

ALERTS = {
    "ui_alert_dust_bin_full": "Please empty dust bin",
    "ui_alert_recovering_location": "Returning to start",
    "ui_alert_battery_chargebasecommerr": "Battery error",
    "ui_alert_busy_charging": "Busy charging",
    "ui_alert_charging_base": "Base charging",
    "ui_alert_charging_power": "Charging power",
    "ui_alert_connect_chrg_cable": "Connect charge cable",
    "ui_alert_info_thank_you": "Thank you",
    "ui_alert_invalid": "Invalid check app",
    "ui_alert_old_error": "Old error",
    "ui_alert_swupdate_fail": "Update failed",
    "dustbin_full": "Please empty dust bin",
    "maint_brush_change": "Change the brush",
    "maint_filter_change": "Change the filter",
    "clean_completed_to_start": "Cleaning completed",
    "nav_floorplan_not_created": "No floorplan found",
    "nav_floorplan_load_fail": "Failed to load floorplan",
    "nav_floorplan_localization_fail": "Failed to load floorplan",
    "clean_incomplete_to_start": "Cleaning incomplete",
    "log_upload_failed": "Logs failed to upload",
}


def setup(hass, config):
    """Set up the Neato component."""
    from pybotvac import Account, Neato, Vorwerk

    if config[DOMAIN][CONF_VENDOR] == "neato":
        hass.data[NEATO_LOGIN] = NeatoHub(hass, config[DOMAIN], Account, Neato)
    elif config[DOMAIN][CONF_VENDOR] == "vorwerk":
        hass.data[NEATO_LOGIN] = NeatoHub(hass, config[DOMAIN], Account, Vorwerk)
    hub = hass.data[NEATO_LOGIN]
    if not hub.login():
        _LOGGER.debug("Failed to login to Neato API")
        return False
    hub.update_robots()
    for component in ("camera", "vacuum", "switch"):
        discovery.load_platform(hass, component, DOMAIN, {}, config)

    return True


class NeatoHub:
    """A My Neato hub wrapper class."""

    def __init__(self, hass, domain_config, neato, vendor):
        """Initialize the Neato hub."""
        self.config = domain_config
        self._neato = neato
        self._hass = hass
        self._vendor = vendor

        self.my_neato = neato(
            domain_config[CONF_USERNAME], domain_config[CONF_PASSWORD], vendor
        )
        self._hass.data[NEATO_ROBOTS] = self.my_neato.robots
        self._hass.data[NEATO_PERSISTENT_MAPS] = self.my_neato.persistent_maps
        self._hass.data[NEATO_MAP_DATA] = self.my_neato.maps

    def login(self):
        """Login to My Neato."""
        try:
            _LOGGER.debug("Trying to connect to Neato API")
            self.my_neato = self._neato(
                self.config[CONF_USERNAME], self.config[CONF_PASSWORD], self._vendor
            )
            return True
        except HTTPError:
            _LOGGER.error("Unable to connect to Neato API")
            return False

    @Throttle(timedelta(seconds=300))
    def update_robots(self):
        """Update the robot states."""
        _LOGGER.debug("Running HUB.update_robots %s", self._hass.data[NEATO_ROBOTS])
        self._hass.data[NEATO_ROBOTS] = self.my_neato.robots
        self._hass.data[NEATO_PERSISTENT_MAPS] = self.my_neato.persistent_maps
        self._hass.data[NEATO_MAP_DATA] = self.my_neato.maps

    def download_map(self, url):
        """Download a new map image."""
        map_image_data = self.my_neato.get_map_image(url)
        return map_image_data
