"""Handle auto setup of IHC products from the ihc project file."""
import logging
import os.path

from defusedxml import ElementTree
import voluptuous as vol

from homeassistant.config import load_yaml_config_file
from homeassistant.const import CONF_TYPE, CONF_UNIT_OF_MEASUREMENT, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers import discovery
import homeassistant.helpers.config_validation as cv

from .const import (
    AUTO_SETUP_YAML,
    CONF_BINARY_SENSOR,
    CONF_DIMMABLE,
    CONF_INVERTING,
    CONF_LIGHT,
    CONF_NODE,
    CONF_SENSOR,
    CONF_SWITCH,
    CONF_XPATH,
    DOMAIN,
    IHC_PLATFORMS,
)

_LOGGER = logging.getLogger(__name__)


AUTO_SETUP_SCHEMA = vol.Schema(
    {
        vol.Optional(CONF_BINARY_SENSOR, default=[]): vol.All(
            cv.ensure_list,
            [
                vol.All(
                    {
                        vol.Required(CONF_NODE): cv.string,
                        vol.Required(CONF_XPATH): cv.string,
                        vol.Optional(CONF_INVERTING, default=False): cv.boolean,
                        vol.Optional(CONF_TYPE): cv.string,
                    }
                )
            ],
        ),
        vol.Optional(CONF_LIGHT, default=[]): vol.All(
            cv.ensure_list,
            [
                vol.All(
                    {
                        vol.Required(CONF_NODE): cv.string,
                        vol.Required(CONF_XPATH): cv.string,
                        vol.Optional(CONF_DIMMABLE, default=False): cv.boolean,
                    }
                )
            ],
        ),
        vol.Optional(CONF_SENSOR, default=[]): vol.All(
            cv.ensure_list,
            [
                vol.All(
                    {
                        vol.Required(CONF_NODE): cv.string,
                        vol.Required(CONF_XPATH): cv.string,
                        vol.Optional(
                            CONF_UNIT_OF_MEASUREMENT, default=UnitOfTemperature.CELSIUS
                        ): cv.string,
                    }
                )
            ],
        ),
        vol.Optional(CONF_SWITCH, default=[]): vol.All(
            cv.ensure_list,
            [
                vol.All(
                    {
                        vol.Required(CONF_NODE): cv.string,
                        vol.Required(CONF_XPATH): cv.string,
                    }
                )
            ],
        ),
    }
)


def autosetup_ihc_products(hass: HomeAssistant, config, ihc_controller, controller_id):
    """Auto setup of IHC products from the IHC project file."""
    if not (project_xml := ihc_controller.get_project()):
        _LOGGER.error("Unable to read project from IHC controller")
        return False
    project = ElementTree.fromstring(project_xml)

    # If an auto setup file exist in the configuration it will override
    yaml_path = hass.config.path(AUTO_SETUP_YAML)
    if not os.path.isfile(yaml_path):
        yaml_path = os.path.join(os.path.dirname(__file__), AUTO_SETUP_YAML)
    yaml = load_yaml_config_file(yaml_path)
    try:
        auto_setup_conf = AUTO_SETUP_SCHEMA(yaml)
    except vol.Invalid as exception:
        _LOGGER.error("Invalid IHC auto setup data: %s", exception)
        return False

    groups = project.findall(".//group")
    for platform in IHC_PLATFORMS:
        platform_setup = auto_setup_conf[platform]
        discovery_info = get_discovery_info(platform_setup, groups, controller_id)
        if discovery_info:
            discovery.load_platform(hass, platform, DOMAIN, discovery_info, config)

    return True


def get_discovery_info(platform_setup, groups, controller_id):
    """Get discovery info for specified IHC platform."""
    discovery_data = {}
    for group in groups:
        groupname = group.attrib["name"]
        for product_cfg in platform_setup:
            products = group.findall(product_cfg[CONF_XPATH])
            for product in products:
                product_id = int(product.attrib["id"].strip("_"), 0)
                nodes = product.findall(product_cfg[CONF_NODE])
                for node in nodes:
                    if "setting" in node.attrib and node.attrib["setting"] == "yes":
                        continue
                    ihc_id = int(node.attrib["id"].strip("_"), 0)
                    name = f"{groupname}_{ihc_id}"
                    # make the model number look a bit nicer - strip leading _
                    model = product.get("product_identifier", "").lstrip("_")
                    device = {
                        "ihc_id": ihc_id,
                        "ctrl_id": controller_id,
                        "product": {
                            "id": product_id,
                            "name": product.get("name") or "",
                            "note": product.get("note") or "",
                            "position": product.get("position") or "",
                            "model": model,
                            "group": groupname,
                        },
                        "product_cfg": product_cfg,
                    }
                    discovery_data[name] = device
    return discovery_data