"""
Kuwait-specific Form helpers
"""
from __future__ import unicode_literals

import re
from datetime import date

from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field
from django.utils.translation import gettext as _

id_re = re.compile(r'^(?P<initial>\d{1})(?P<yy>\d\d)(?P<mm>\d\d)(?P<dd>\d\d)(?P<mid>\d{4})(?P<checksum>\d{1})')

class KWCivilIDNumberField(Field):
    """
    Kuwaiti Civil ID numbers are 12 digits, second to seventh digits
    represents the person's birthdate.

    Checks the following rules to determine the validty of the number:
        * The number consist of 12 digits.
        * The birthdate of the person is a valid date.
        * The calculated checksum equals to the last digit of the Civil ID.
    """
    default_error_messages = {
        'invalid': _('Enter a valid Kuwaiti Civil ID number'),
    }

    def has_valid_checksum(self, value):
        weight = (2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2)
        calculated_checksum = 0
        for i in range(11):
            calculated_checksum += int(value[i]) * weight[i]

        remainder = calculated_checksum % 11
        checkdigit = 11 - remainder
        if checkdigit != int(value[11]):
            return False
        return True

    def clean(self, value):
        super(KWCivilIDNumberField, self).clean(value)
        if value in EMPTY_VALUES:
            return ''

        if not re.match(r'^\d{12}$', value):
            raise ValidationError(self.error_messages['invalid'])

        match = re.match(id_re, value)

        if not match:
            raise ValidationError(self.error_messages['invalid'])

        gd = match.groupdict()

        try:
            d = date(int(gd['yy']), int(gd['mm']), int(gd['dd']))
        except ValueError:
            raise ValidationError(self.error_messages['invalid'])

        if not self.has_valid_checksum(value):
            raise ValidationError(self.error_messages['invalid'])

        return value
