"""Config flow for Minecraft Server integration."""
import logging

from mcstatus import JavaServer
import voluptuous as vol

from homeassistant.config_entries import ConfigFlow
from homeassistant.const import CONF_ADDRESS, CONF_NAME
from homeassistant.data_entry_flow import FlowResult

from .const import DEFAULT_NAME, DOMAIN

DEFAULT_ADDRESS = "localhost:25565"

_LOGGER = logging.getLogger(__name__)


class MinecraftServerConfigFlow(ConfigFlow, domain=DOMAIN):
    """Handle a config flow for Minecraft Server."""

    VERSION = 3

    async def async_step_user(self, user_input=None) -> FlowResult:
        """Handle the initial step."""
        errors = {}

        if user_input:
            address = user_input[CONF_ADDRESS]

            if await self._async_is_server_online(address):
                # No error was detected, create configuration entry.
                config_data = {CONF_NAME: user_input[CONF_NAME], CONF_ADDRESS: address}
                return self.async_create_entry(title=address, data=config_data)

            # Host or port invalid or server not reachable.
            errors["base"] = "cannot_connect"

        # Show configuration form (default form in case of no user_input,
        # form filled with user_input and eventually with errors otherwise).
        return self._show_config_form(user_input, errors)

    def _show_config_form(self, user_input=None, errors=None) -> FlowResult:
        """Show the setup form to the user."""
        if user_input is None:
            user_input = {}

        return self.async_show_form(
            step_id="user",
            data_schema=vol.Schema(
                {
                    vol.Required(
                        CONF_NAME, default=user_input.get(CONF_NAME, DEFAULT_NAME)
                    ): str,
                    vol.Required(
                        CONF_ADDRESS,
                        default=user_input.get(CONF_ADDRESS, DEFAULT_ADDRESS),
                    ): vol.All(str, vol.Lower),
                }
            ),
            errors=errors,
        )

    async def _async_is_server_online(self, address: str) -> bool:
        """Check server connection using a 'status' request and return result."""

        # Parse and check server address.
        try:
            server = await JavaServer.async_lookup(address)
        except ValueError as error:
            _LOGGER.debug(
                (
                    "Error occurred while parsing server address '%s' -"
                    " ValueError: %s"
                ),
                address,
                error,
            )
            return False

        # Send a status request to the server.
        try:
            await server.async_status()
            return True
        except OSError as error:
            _LOGGER.debug(
                (
                    "Error occurred while trying to check the connection to '%s:%s' -"
                    " OSError: %s"
                ),
                server.address.host,
                server.address.port,
                error,
            )

        return False