"""
This module defines operating system user related forms.

"""
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit
from django import forms
from django.urls import reverse
from django.utils.translation import gettext_lazy as _

from gvawebcore.forms import PasswordModelFormMixin

from .models import SshPublicKey, User

INVALID_SSH_PUBLIC_KEY = _("Invalid SSH public key data format.")
DUPLICATE_SSH_PUBLIC_KEY_FOR_USER = _(
    "This SSH public key is already assigned to this user."
)


class ChangeOsUserPasswordForm(PasswordModelFormMixin, forms.ModelForm):
    """
    A form for setting an OS user's password.

    """

    class Meta:
        model = User
        fields = []

    def __init__(self, *args, **kwargs):
        self.helper = FormHelper()
        super(ChangeOsUserPasswordForm, self).__init__(*args, **kwargs)
        self.helper.form_action = reverse(
            "set_osuser_password", kwargs={"slug": self.instance.username}
        )
        self.helper.add_input(Submit("submit", _("Set password")))

    def save(self, commit=True):
        """
        Save the provided password in hashed format.

        :param boolean commit: whether to save the created user
        :return: user instance
        :rtype: :py:class:`osusers.models.User`

        """
        self.instance.set_password(self.cleaned_data["password1"])
        return super(ChangeOsUserPasswordForm, self).save(commit=commit)


class AddSshPublicKeyForm(forms.ModelForm):
    """
    A form for creating :py:class:`SSH public keys
    <osusers.models.SshPublicKey>`.

    """

    publickeytext = forms.CharField(
        label=_("Key text"),
        widget=forms.Textarea,
        help_text=_("A SSH public key in either OpenSSH or RFC 4716 format"),
    )

    class Meta:
        model = SshPublicKey
        fields = []

    def __init__(self, *args, **kwargs):
        hosting_package = kwargs.pop("hostingpackage")
        self.osuser = hosting_package.osuser
        super(AddSshPublicKeyForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_action = reverse(
            "add_ssh_key", kwargs={"package": hosting_package.id}
        )
        self.helper.add_input(Submit("submit", _("Add SSH public key")))

    def clean_publickeytext(self):
        keytext = self.cleaned_data.get("publickeytext")
        try:
            SshPublicKey.objects.parse_key_text(keytext)
        except ValueError:
            raise forms.ValidationError(INVALID_SSH_PUBLIC_KEY)
        return keytext

    def clean(self):
        keytext = self.cleaned_data.get("publickeytext")
        if keytext is not None:
            alg, data, comment = SshPublicKey.objects.parse_key_text(keytext)
            if SshPublicKey.objects.filter(
                user=self.osuser, algorithm=alg, data=data
            ).exists():
                self.add_error(
                    "publickeytext",
                    forms.ValidationError(DUPLICATE_SSH_PUBLIC_KEY_FOR_USER),
                )

    def save(self, commit=True):
        """
        Save the provided ssh public key in properly split format.

        :param boolean commit: whether to save the created public key
        :return: ssh public key instance
        :rtype: :py:class:`osusers.models.SshPublicKey`

        """
        algorithm, keydata, comment = SshPublicKey.objects.parse_key_text(
            self.cleaned_data.get("publickeytext")
        )
        self.instance.user = self.osuser
        self.instance.algorithm = algorithm
        self.instance.data = keydata
        self.instance.comment = comment
        return super(AddSshPublicKeyForm, self).save(commit)


class EditSshPublicKeyCommentForm(forms.ModelForm):
    """
    A form for editing :py:class:`SSH public key
    <osusers.models.SshPublicKey>` comment fields.

    """

    class Meta:
        model = SshPublicKey
        fields = ["comment"]

    def __init__(self, *args, **kwargs):
        hosting_package = kwargs.pop("hostingpackage")
        self.osuser = hosting_package.osuser
        super(EditSshPublicKeyCommentForm, self).__init__(*args, **kwargs)
        self.fields["comment"].widget = forms.TextInput()
        self.helper = FormHelper()
        self.helper.form_action = reverse(
            "edit_ssh_key_comment",
            kwargs={"package": hosting_package.id, "pk": self.instance.id},
        )
        self.helper.add_input(Submit("submit", _("Change Comment")))
