""" config flow """
from collections import OrderedDict
import logging
from homeassistant.core import callback
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant import config_entries
from datetime import datetime
import uuid

from .const import (
    DOMAIN,
    DEFAULT_ICON_NORMAL,
    DEFAULT_ICON_SOON,
    DEFAULT_ICON_TODAY,
    DEFAULT_DATE_FORMAT,
    DEFAULT_SOON,
    DEFAULT_HALF_ANNIVERSARY,
    DEFAULT_UNIT_OF_MEASUREMENT,
    DEFAULT_ID_PREFIX,
    DEFAULT_ONE_TIME,
    CONF_SENSOR,
    CONF_ENABLED,
    CONF_ICON_NORMAL,
    CONF_ICON_TODAY,
    CONF_ICON_SOON,
    CONF_DATE,
    CONF_DATE_FORMAT,
    CONF_SENSORS,
    CONF_SOON,
    CONF_HALF_ANNIVERSARY,
    CONF_UNIT_OF_MEASUREMENT,
    CONF_ID_PREFIX,
    CONF_ONE_TIME,
)

from homeassistant.const import CONF_NAME

_LOGGER = logging.getLogger(__name__)


@config_entries.HANDLERS.register(DOMAIN)
class AnniversariesFlowHandler(config_entries.ConfigFlow):
    CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL

    def __init__(self):
        self._errors = {}
        self._data = {}
        self._data["unique_id"] = str(uuid.uuid4())

    async def async_step_user(self, user_input=None):   # pylint: disable=unused-argument
        self._errors = {}
        if user_input is not None:
            self._data.update(user_input)
            if is_not_date(user_input[CONF_DATE], user_input[CONF_ONE_TIME]):
                self._errors["base"] = "invalid_date"
            if self._errors == {}:
                self.init_info = user_input
                return await self.async_step_icons()
        return await self._show_user_form(user_input)
    
    async def async_step_icons(self, user_input=None):
        self._errors = {}
        if user_input is not None:
            self._data.update(user_input)
            return self.async_create_entry(title=self._data["name"], data=self._data)
        return await self._show_icon_form(user_input)

    async def _show_user_form(self, user_input):
        name = ""
        date = ""
        one_time = DEFAULT_ONE_TIME
        half_anniversary = DEFAULT_HALF_ANNIVERSARY
        date_format = DEFAULT_DATE_FORMAT
        unit_of_measurement = DEFAULT_UNIT_OF_MEASUREMENT
        id_prefix = DEFAULT_ID_PREFIX
        if user_input is not None:
            if CONF_NAME in user_input:
                name = user_input[CONF_NAME]
            if CONF_DATE in user_input:
                date = user_input[CONF_DATE]
            if CONF_ONE_TIME in user_input:
                one_time = user_input[CONF_ONE_TIME]
            if CONF_HALF_ANNIVERSARY in user_input:
                half_anniversary = user_input[CONF_HALF_ANNIVERSARY]
            if CONF_DATE_FORMAT in user_input:
                date_format = user_input[CONF_DATE_FORMAT]
            if CONF_UNIT_OF_MEASUREMENT in user_input:
                unit_of_measurement = user_input[CONF_UNIT_OF_MEASUREMENT]
            if CONF_ID_PREFIX in user_input:
                id_prefix = user_input[CONF_ID_PREFIX]
        data_schema = OrderedDict()
        data_schema[vol.Required(CONF_NAME, default=name)] = str
        data_schema[vol.Required(CONF_DATE, default=date)] = str
        data_schema[vol.Required(CONF_ONE_TIME, default=one_time)] = bool
        data_schema[vol.Required(CONF_HALF_ANNIVERSARY, default=half_anniversary)] = bool
        data_schema[vol.Required(CONF_DATE_FORMAT, default=date_format)] = str
        data_schema[vol.Required(CONF_UNIT_OF_MEASUREMENT, default=unit_of_measurement)] = str
        data_schema[vol.Optional(CONF_ID_PREFIX, default=id_prefix)] = str
        return self.async_show_form(step_id="user", data_schema=vol.Schema(data_schema), errors=self._errors)

    async def _show_icon_form(self, user_input):
        icon_normal = DEFAULT_ICON_NORMAL
        icon_today = DEFAULT_ICON_TODAY
        days_as_soon = DEFAULT_SOON
        icon_soon = DEFAULT_ICON_SOON
        if user_input is not None:
            if CONF_ICON_NORMAL in user_input:
                icon_normal = user_input[CONF_ICON_NORMAL]
            if CONF_ICON_TODAY in user_input:
                icon_today = user_input[CONF_ICON_TODAY]
            if CONF_SOON in user_input:
                days_as_soon = user_input[CONF_SOON]
            if CONF_ICON_SOON in user_input:
                icon_soon = user_input[CONF_ICON_SOON]
        data_schema = OrderedDict()
        data_schema[vol.Required(CONF_ICON_NORMAL, default=icon_normal)] = str
        data_schema[vol.Required(CONF_ICON_TODAY, default=icon_today)] = str
        data_schema[vol.Required(CONF_SOON, default=days_as_soon)] = int
        data_schema[vol.Required(CONF_ICON_SOON, default=icon_soon)] = str
        return self.async_show_form(step_id="icons", data_schema=vol.Schema(data_schema), errors=self._errors)

    async def async_step_import(self, user_input):  # pylint: disable=unused-argument
        """Import a config entry.
        Special type of import, we're not actually going to store any data.
        Instead, we're going to rely on the values that are in config file.
        """
        if self._async_current_entries():
            return self.async_abort(reason="single_instance_allowed")

        return self.async_create_entry(title="configuration.yaml", data={})

    @staticmethod
    @callback
    def async_get_options_flow(config_entry):
        if config_entry.options.get("unique_id", None) is not None:
            return OptionsFlowHandler(config_entry)
        else:
            return EmptyOptions(config_entry)

def is_not_date(date, one_time):
    try:
        datetime.strptime(date, "%Y-%m-%d")
        return False
    except ValueError:
        if not one_time:
            pass
        else:
            return True
    try:
        datetime.strptime(date, "%m-%d")
        return False
    except ValueError:
        return True
        
class OptionsFlowHandler(config_entries.OptionsFlow):
    def __init__(self, config_entry):
        self.config_entry = config_entry
        self._data = {}
        self._data["unique_id"] = config_entry.options.get("unique_id")

    async def async_step_init(self, user_input=None):
        self._errors = {}
        if user_input is not None:
            self._data.update(user_input)
            if is_not_date(user_input[CONF_DATE], user_input[CONF_ONE_TIME]):
                self._errors["base"] = "invalid_date"
            if self._errors == {}:
                return await self.async_step_icons()
        return await self._show_init_form(user_input)

    async def async_step_icons(self, user_input=None):
        self._errors = {}
        if user_input is not None:
            self._data.update(user_input)
            return self.async_create_entry(title="", data=self._data)
        return await self._show_icon_form(user_input)

    async def _show_init_form(self, user_input):
        data_schema = OrderedDict()
        one_time = self.config_entry.options.get(CONF_ONE_TIME)
        unit_of_measurement = self.config_entry.options.get(CONF_UNIT_OF_MEASUREMENT)
        half_anniversary = self.config_entry.options.get(CONF_HALF_ANNIVERSARY)
        if one_time is None:
            one_time = DEFAULT_ONE_TIME
        if half_anniversary is None:
            half_anniversary = DEFAULT_HALF_ANNIVERSARY
        if unit_of_measurement is None:
            unit_of_measurement = DEFAULT_UNIT_OF_MEASUREMENT
        data_schema[vol.Required(CONF_NAME,default=self.config_entry.options.get(CONF_NAME),)] = str
        data_schema[vol.Required(CONF_DATE, default=self.config_entry.options.get(CONF_DATE),)] = str
        data_schema[vol.Required(CONF_ONE_TIME, default=one_time,)] = bool
        data_schema[vol.Required(CONF_HALF_ANNIVERSARY,default=half_anniversary,)] = bool
        data_schema[vol.Required(CONF_DATE_FORMAT,default=self.config_entry.options.get(CONF_DATE_FORMAT),)] = str
        data_schema[vol.Required(CONF_UNIT_OF_MEASUREMENT,default=unit_of_measurement,)] = str
        return self.async_show_form(
            step_id="init", data_schema=vol.Schema(data_schema), errors=self._errors
        )

    async def _show_icon_form(self, user_input):
        data_schema = OrderedDict()
        data_schema[vol.Required(CONF_ICON_NORMAL,default=self.config_entry.options.get(CONF_ICON_NORMAL),)] = str
        data_schema[vol.Required(CONF_ICON_TODAY,default=self.config_entry.options.get(CONF_ICON_TODAY),)] = str
        data_schema[vol.Required(CONF_SOON,default=self.config_entry.options.get(CONF_SOON),)] = int
        data_schema[vol.Required(CONF_ICON_SOON,default=self.config_entry.options.get(CONF_ICON_SOON),)] = str
        return self.async_show_form(step_id="icons", data_schema=vol.Schema(data_schema), errors=self._errors)


class EmptyOptions(config_entries.OptionsFlow):
    def __init__(self, config_entry):
        self.config_entry = config_entry