class ForisAjaxForm(object):
class ForisFormElement(object):
class ForisForm(ForisFormElement):
class Section(ForisFormElement):
class Field(ForisFormElement):
    def make_form(self, data: typing.Optional[dict]):
    def convert_data_from_form_to_backend(self, *args, **kwargs):
    def convert_data_from_backend_to_form(self, *args, **kwargs):
    def __init__(self, data=None, controller_id=None):
    def __init__(self, name):
    def __iter__(self):
    def _add(self, child):
    def _remove(self, child):
    def sections(self):
    def __init__(self, name, data=None, validators=[]):
    def data(self):
    def current_data(self):
    def clean_data(self, data):
    def invalidate_data(self):
    def _form(self):
    def valid(self):
    def _get_all_fields(self, element=None, fields=None):
    def get_active_fields(self, element=None, data=None):
    def add_section(self, *args, **kwargs):
    def active_fields(self):
    def errors(self):
    def render_errors(self):
    def render(self):
    def save(self):
    def validate(self):
    def add_callback(self, cb):
    def process_callbacks(self, form_data):
    def __init__(self, main_form, name, title, description=None):
    def active_fields(self):
    def add_field(self, *args, **kwargs):
    def add_section(self, *args, **kwargs):
    def render(self):
    def __init__(
        self,
        main_form,
        type,
        name,
        label=None,
        required=False,
        preproc=None,
        validators=None,
        hint="",
        multifield=False,
        **kwargs
    ):
    def __str__(self):
    def _generate_html_classes(self):
    def _generate_html_data(self):
    def field(self):
    def html_id(self):
    def label_tag(self):
        def create_label(text):
    def errors(self):
    def hidden(self):
    def render(self):
    def requires(self, field, value=None):
    def has_requirements(self, data): class Validator(object):
class RegExp(Validator):
class NotEmpty(Validator):
class IPv4(Validator):
class IPv4Netmask(Validator):
class IPv6(Validator):
class AnyIP(Validator):
class IPv6Prefix(Validator):
class IPv4Prefix(Validator):
class PositiveInteger(Validator):
class Time(RegExp):
class Datetime(Validator):
class FloatRange(Validator):
class Domain(Validator):
class MacAddress(Validator):
class Duid(Validator):
class InRange(Validator):
class LenRange(Validator):
class ByteLenRange(Validator):
class EqualTo(Validator):
class RequiredWithOtherFields(Validator):
class DhcpRangeValidator:
class DhcpRangeRouterIpValidator:
    def __deepcopy__(self, memo):
    def __init__(self, msg):
    def valid(self, value):
def convert_to_anchored_pattern(pattern):
    def __init__(self, msg, reg_exp):
    def valid(self, value):
    def __init__(self):
    def valid(self, value):
    def __init__(self):
    def valid(self, value):
    def __init__(self):
    def valid(self, value):
    def __init__(self):
    def valid(self, value):
    def __init__(self):
    def valid(self, value):
    def __init__(self):
    def valid(self, value):
    def __init__(self):
    def valid(self, value):
    def __init__(self):
    def valid(self, value):
    def __init__(self):
    def __init__(self):
    def valid(self, value):
    def __init__(self, low, high):
    def valid(self, value):
    def __init__(self):
    def valid(self, value):
    def __init__(self):
    def valid(self, value):
    def __init__(self):
    def valid(self, value):
    def __init__(self, low, high):
    def valid(self, value):
    def __init__(self, low, high):
    def valid(self, value):
    def __init__(self, low, high):
    def valid(self, value):
    def __init__(self, field1, field2, message):
    def valid(self, data):
    def __init__(self, fields, message):
    def valid(self, data):
    def __init__(self, netmask_field, dhcp_start_field, dhcp_limit_field, msg, skip_conditions=[]):
    def valid(self, data):
    def __init__(
        self,
        router_ip_field,
        netmask_field,
        dhcp_start_field,
        dhcp_limit_field,
        msg,
        skip_conditions=[],
    ):
    def valid(self, data):
def validators_as_data_dict(validators): class Password(Input):
    """Password input.

        >>> Password(name='password', value='secret').render()
        u'<input type="password" id="field-password" value="secret" name="password"/>'
    """

    def get_type(self):
        return "password" class Textbox(Input):
    """Textbox input.

        >>> Textbox(name='foo', value='bar').render()
        u'<input type="text" id="field-foo" value="bar" name="foo"/>'
        >>> Textbox(name='foo', value=0).render()
        u'<input type="text" id="field-foo" value="0" name="foo"/>'
    """

    def get_type(self):
        return "text" class Dropdown(InputWithArgs):
    r"""Dropdown/select input.

        >>> Dropdown(name='foo', args=['a', 'b', 'c'], value='b').render()
        u'<input type="hidden" name="foo" value=""><select id="field-foo" name="foo">\n  <option value="a">a</option>\n  <option selected="selected" value="b">b</option>\n  <option value="c">c</option>\n</select>\n'
        >>> Dropdown(name='foo', args=[('a', 'aa'), ('b', 'bb'), ('c', 'cc')], value='b').render()
        u'<input type="hidden" name="foo" value=""><select id="field-foo" name="foo">\n  <option value="a">aa</option>\n  <option selected="selected" value="b">bb</option>\n  <option value="c">cc</option>\n</select>\n'
    """

    def render(self):
        attrs = self.attrs.copy()
        attrs["name"] = self.name
        # dummy value to post when no item is selected
        x = '<input type="hidden" name="%s" value="">' % self.name
        x += "<select %s>\n" % attrs

        for arg in self.args:
            x += self._render_option(arg)

        x += "</select>\n"
        return x

    def _render_option(self, arg, indent="  "):
        if isinstance(arg, (tuple, list)):
            value, desc = arg
        else:
            value, desc = arg, arg

        if self.value == value or (isinstance(self.value, list) and value in self.value):
            select_p = ' selected="selected"'
        else:
            select_p = ""
        return indent + '<option%s value="%s">%s</option>\n' % (
            select_p,
            websafe(value),
            websafe(desc),
        ) class Checkbox(Input):
    """Checkbox input.

    >>> Checkbox('foo', value='bar', checked=True).render()
    u'<input type="hidden" name="foo" value="0"><input checked="checked" type="checkbox" id="field-foo_bar" value="bar" name="foo"/>'
    >>> Checkbox('foo', value='bar').render()
    u'<input type="hidden" name="foo" value="0"><input type="checkbox" id="field-foo_bar" value="bar" name="foo"/>'
    >>> c = Checkbox('foo', value='bar')
    >>> c.validate('on')
    True
    >>> c.render()
    u'<input type="hidden" name="foo" value="0"><input type="checkbox" id="field-foo_bar" value="bar" name="foo"/>'
    """

    def __init__(self, name, *validators, **attrs):
        self.checked = attrs.pop("checked", False)
        Input.__init__(self, name, *validators, **attrs)

    def get_default_id(self):
        value = safestr(self.value or "")
        return ID_TEMPLATE % self.name + "_" + value.replace(" ", "_")

    def render(self):
        attrs = self.attrs.copy()
        attrs["type"] = "checkbox"
        attrs["name"] = self.name
        attrs["value"] = self.value

        if self.checked:
            attrs["checked"] = "checked"
        return '<input type="hidden" name="%s" value="0">' "<input %s/>" % (attrs["name"], attrs)

    def set_value(self, value):
        self.checked = bool(value)

    def get_value(self):
        return self.checked class Radio(Input):
    def __init__(self, name, args, *validators, **attrs):
        self.args = args
        super(Radio, self).__init__(name, *validators, **attrs)

    def get_default_id(self):
        return ID_TEMPLATE % self.name + "_%s"

    def render(self):
        rendered = []
        for arg in self.args:
            if isinstance(arg, (tuple, list)):
                value, desc = arg
            else:
                value, desc = arg, arg
            attrs = self.attrs.copy()
            rendered_input = RadioSingle.render_single(value, self.name, self.value, attrs)
            rendered.append(
                '<label for="%s">%s %s</label>' % (attrs["id"], rendered_input, websafe(desc))
            )
        return '<div class="radio-inputs">%s</div>' % "\n".join(rendered) class Number(Input):
    """Number input.

        >>> Number(name='number', value='123').render()
        u'<input type="number" id="field-number" value="123" name="number"/>'
    """

    def get_type(self):
        return "number" class Email(Input):
    """Email input.

        >>> Email(name='email', value='mail@example.com').render()
        u'<input type="email" id="field-email" value="mail@example.com" name="email"/>'
    """

    def get_type(self):
        return "email" class Time(Input):
    """Password input.

        >>> Time(name='time', value='11:22').render()
        u'<input type="time" id="field-time" value="11:22" name="time"/>'
    """

    def get_type(self):
        return "time" class ForisState(object):
    def __init__(self):
    def update_lang(self, lang):
    def set_app(self, app):
    def set_backend(self, backend):
    def set_websocket(self, ws_port, ws_path, wss_port, wss_path):
    def update_reboot_required(self, required):
    def update_notification_count(self, new_count):
    def repr(self):
    def set_updater_is_running(self, running):
    def set_turris_os_version(self, version):
    def set_device(self, device):
    def update_password_set(self, password_set):
    def update_guide(self, guide_data):
    def set_assets_path(self, assets_path):
    def set_sentry(self, running): class _LangDict(collections.OrderedDict):
class SimpleDelayedTranslator(object):
class ForisInternationalizationExtension(InternationalizationExtension):
    def __missing__(self, key):
    def __init__(self, text):
    def __str__(self):
    def __add__(self, other):
def set_current_language(language):
    def __init__(self, environment): class BaseConfigHandler(object):
    def __init__(self, data=None):
        self.data = data
        self.__form_cache = None

    @property
    def form(self):
        if self.__form_cache is None:
            self.__form_cache = self.get_form()
        return self.__form_cache

    def get_form(self):
        """Get form. MUST be a single-section form.

        :return:
        :rtype: fapi.ForisForm
        """
        raise NotImplementedError()

    def save(self, extra_callbacks=None):
        """

        :param extra_callbacks: list of extra callbacks to call when saved
        :return:
        """
        form = self.form
        form.validate()
        if extra_callbacks:
            for cb in extra_callbacks:
                form.add_callback(cb)
        if form.valid:
            form.save()
            return True
        else:
            return False
from foris import fapi, validators
from foris.form import Password, Textbox, Dropdown, Checkbox, Radio, Number, Email, Time
from foris.state import current_state
from foris.utils.translators import gettext_dummy as gettext, _
from .base import BaseConfigHandler
# Copyright (C) 2017 CZ.NIC, z.s.p.o. <http://www.nic.cz>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.




class NotificationsHandler(BaseConfigHandler):
    userfriendly_title = gettext("Notifications")

    def get_form(self):
        data = current_state.backend.perform("router_notifications", "get_settings")
        data["enable_smtp"] = data["emails"]["enabled"]
        data["use_turris_smtp"] = "1" if data["emails"]["smtp_type"] == "turris" else "0"
        data["to"] = " ".join(data["emails"]["common"]["to"])
        data["sender_name"] = data["emails"]["smtp_turris"]["sender_name"]
        data["severity"] = data["emails"]["common"]["severity_filter"]
        data["news"] = data["emails"]["common"]["send_news"]
        data["from"] = data["emails"]["smtp_custom"]["from"]
        data["server"] = data["emails"]["smtp_custom"]["host"]
        data["port"] = data["emails"]["smtp_custom"]["port"]
        data["security"] = data["emails"]["smtp_custom"]["security"]
        data["username"] = data["emails"]["smtp_custom"]["username"]
        data["password"] = data["emails"]["smtp_custom"]["password"]
        data["delay"] = str(data["reboots"]["delay"])
        data["reboot_time"] = data["reboots"]["time"]

        if self.data:
            # Update from post
            data.update(self.data)

        notifications_form = fapi.ForisForm("notifications", data)

        notifications = notifications_form.add_section(
            name="notifications", title=_("Notifications settings")
        )
        # notifications settings
        notifications.add_field(
            Checkbox, name="enable_smtp", label=_("Enable notifications"), default=False
        )

        notifications.add_field(
            Radio,
            name="use_turris_smtp",
            label=_("SMTP provider"),
            default="0",
            args=(("1", _("Turris")), ("0", _("Custom"))),
            hint=_(
                'If you set SMTP provider to "Turris", the servers provided to members of the '
                "Turris project would be used. These servers do not require any additional "
                'settings. If you want to set your own SMTP server, please select "Custom" '
                "and enter required settings."
            ),
        ).requires("enable_smtp", True)

        notifications.add_field(
            Textbox,
            name="to",
            label=_("Recipient's email"),
            hint=_("Email address of recipient. Separate multiple addresses by spaces."),
            required=True,
            validators=[
                validators.RegExp(
                    _("Doesn't contain a list of emails separated by spaces"),
                    r"^([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+ *)( +[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+ *)*$",
                )
            ],
        ).requires("enable_smtp", True)

        # sender's name for CZ.NIC SMTP only
        notifications.add_field(
            Textbox,
            name="sender_name",
            label=_("Sender's name"),
            hint=_(
                "Name of the sender - will be used as a part of the "
                'sender\'s email address before the "at" sign.'
            ),
            validators=[
                validators.RegExp(
                    _(
                        "Sender's name can contain only alphanumeric characters, dots "
                        "and underscores."
                    ),
                    r"^[0-9a-zA-Z_\.-]+$",
                )
            ],
            required=True,
        ).requires("enable_smtp", True).requires("use_turris_smtp", "1")

        SEVERITY_OPTIONS = (
            (1, _("Reboot is required")),
            (2, _("Reboot or attention is required")),
            (3, _("Reboot or attention is required or update was installed")),
        )
        notifications.add_field(
            Dropdown, name="severity", label=_("Importance"), args=SEVERITY_OPTIONS, default=1
        ).requires("enable_smtp", True)
        notifications.add_field(
            Checkbox,
            name="news",
            label=_("Send news"),
            hint=_("Send emails about new features."),
            default=True,
        ).requires("enable_smtp", True)

        # SMTP settings (custom server)
        smtp = notifications_form.add_section(name="smtp", title=_("SMTP settings"))
        smtp.add_field(

            Email,