from django.forms import ValidationError

from staff.lib.forms.staff_form import StaffForm
from staff.lib.forms.staff_fields import (
    StaffCharField,
    StaffIntegerField,
)
from staff.keys.models import GPGKey
from ..controllers.gpg_key import (
    gpg_fingerprint,
    GPGKeyError,
)


class GPGKeyIdValidator(object):

    def __call__(self, value):
        if value and not (
                GPGKey.objects
                      .filter(id=value)
                      .exists()):
            raise ValidationError(
                '{"error_key": "staff-invalid_gpg_key_id"}',
                code='staff_invalid_gpg_key_id')


gpg_key_id_validator = GPGKeyIdValidator()


class GPGKeyForm(StaffForm):
    strip_fields = ['key', 'description']

    id = StaffIntegerField(
        required=False,
        validators=[gpg_key_id_validator],
        front_params={'hidden': True},
    )
    fingerprint = StaffCharField(required=False)
    key = StaffCharField(required=False)
    description = StaffCharField(required=False)

    def _has_id(self):
        return bool(self.cleaned_data.get('id'))

    def clean(self):
        cleaned_data = super(GPGKeyForm, self).clean()
        if self._has_id():
            cleaned_data.pop('key', None)
            cleaned_data.pop('fingerprint', None)
        else:
            key = self.cleaned_data['key'].strip()
            try:
                fingerprint = gpg_fingerprint(key)

                if GPGKey.objects.filter(fingerprint=fingerprint).exists():
                    self._errors['key'] = ['{"error_key": "staff-already_used_key_gpg_key_field"}']

                cleaned_data['fingerprint'] = fingerprint
            except GPGKeyError:
                self._errors['key'] = ['{"error_key": "staff-general_gpg_key_field"}']

        return cleaned_data
