"""
Register a custom front end panel.

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

import voluptuous as vol

from homeassistant.loader import bind_hass
import homeassistant.helpers.config_validation as cv

DOMAIN = 'panel_custom'
DEPENDENCIES = ['frontend']

CONF_COMPONENT_NAME = 'name'
CONF_SIDEBAR_TITLE = 'sidebar_title'
CONF_SIDEBAR_ICON = 'sidebar_icon'
CONF_URL_PATH = 'url_path'
CONF_CONFIG = 'config'
CONF_WEBCOMPONENT_PATH = 'webcomponent_path'
CONF_JS_URL = 'js_url'
CONF_EMBED_IFRAME = 'embed_iframe'
CONF_TRUST_EXTERNAL_SCRIPT = 'trust_external_script'

DEFAULT_EMBED_IFRAME = False
DEFAULT_TRUST_EXTERNAL = False

DEFAULT_ICON = 'mdi:bookmark'
LEGACY_URL = '/api/panel_custom/{}'

PANEL_DIR = 'panels'

CONFIG_SCHEMA = vol.Schema({
    DOMAIN: vol.All(cv.ensure_list, [vol.Schema({
        vol.Required(CONF_COMPONENT_NAME): cv.string,
        vol.Optional(CONF_SIDEBAR_TITLE): cv.string,
        vol.Optional(CONF_SIDEBAR_ICON, default=DEFAULT_ICON): cv.icon,
        vol.Optional(CONF_URL_PATH): cv.string,
        vol.Optional(CONF_CONFIG): dict,
        vol.Optional(CONF_WEBCOMPONENT_PATH): cv.isfile,
        vol.Optional(CONF_JS_URL): cv.string,
        vol.Optional(CONF_EMBED_IFRAME,
                     default=DEFAULT_EMBED_IFRAME): cv.boolean,
        vol.Optional(CONF_TRUST_EXTERNAL_SCRIPT,
                     default=DEFAULT_TRUST_EXTERNAL): cv.boolean,
    })])
}, extra=vol.ALLOW_EXTRA)

_LOGGER = logging.getLogger(__name__)


@bind_hass
async def async_register_panel(
        hass,
        # The url to serve the panel
        frontend_url_path,
        # The webcomponent name that loads your panel
        webcomponent_name,
        # Title/icon for sidebar
        sidebar_title=None,
        sidebar_icon=None,
        # HTML source of your panel
        html_url=None,
        # JS source of your panel
        js_url=None,
        # If your panel should be run inside an iframe
        embed_iframe=DEFAULT_EMBED_IFRAME,
        # Should user be asked for confirmation when loading external source
        trust_external=DEFAULT_TRUST_EXTERNAL,
        # Configuration to be passed to the panel
        config=None):
    """Register a new custom panel."""
    if js_url is None and html_url is None:
        raise ValueError('Either js_url or html_url is required.')
    elif js_url and html_url:
        raise ValueError('Pass in either JS url or HTML url, not both.')

    if config is not None and not isinstance(config, dict):
        raise ValueError('Config needs to be a dictionary.')

    custom_panel_config = {
        'name': webcomponent_name,
        'embed_iframe': embed_iframe,
        'trust_external': trust_external,
    }

    if js_url is not None:
        custom_panel_config['js_url'] = js_url

    if html_url is not None:
        custom_panel_config['html_url'] = html_url

    if config is not None:
        # Make copy because we're mutating it
        config = dict(config)
    else:
        config = {}

    config['_panel_custom'] = custom_panel_config

    await hass.components.frontend.async_register_built_in_panel(
        component_name='custom',
        sidebar_title=sidebar_title,
        sidebar_icon=sidebar_icon,
        frontend_url_path=frontend_url_path,
        config=config
    )


async def async_setup(hass, config):
    """Initialize custom panel."""
    success = False

    for panel in config.get(DOMAIN):
        name = panel[CONF_COMPONENT_NAME]

        kwargs = {
            'webcomponent_name': panel[CONF_COMPONENT_NAME],
            'frontend_url_path': panel.get(CONF_URL_PATH, name),
            'sidebar_title': panel.get(CONF_SIDEBAR_TITLE),
            'sidebar_icon': panel.get(CONF_SIDEBAR_ICON),
            'config': panel.get(CONF_CONFIG),
            'trust_external': panel[CONF_TRUST_EXTERNAL_SCRIPT],
            'embed_iframe': panel[CONF_EMBED_IFRAME],
        }

        panel_path = panel.get(CONF_WEBCOMPONENT_PATH)

        if panel_path is None:
            panel_path = hass.config.path(
                PANEL_DIR, '{}.html'.format(name))

        if CONF_JS_URL in panel:
            kwargs['js_url'] = panel[CONF_JS_URL]

        elif not await hass.async_add_job(os.path.isfile, panel_path):
            _LOGGER.error('Unable to find webcomponent for %s: %s',
                          name, panel_path)
            continue

        else:
            url = LEGACY_URL.format(name)
            hass.http.register_static_path(url, panel_path)
            kwargs['html_url'] = url

        await async_register_panel(hass, **kwargs)

        success = True

    return success