from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
from django.utils.translation import ugettext, ungettext, ugettext_lazy
from wtforms import Form, StringField, IntegerField, Field, SelectField
from wtforms.validators import DataRequired, ValidationError, URL

from intranet.search.core.validators import MaybeSchemalessURL
from intranet.search.core import storages
from intranet.search.core.fields import MaskField, SplitField, URLField
from intranet.search.core.models import Mark

scope_names = settings.ISEARCH['scopes'].keys()
required_message = ugettext_lazy('This field is required')
url_message = ugettext_lazy('Does not look like a link. Check if the url is correct')


class ListField(StringField):
    def __init__(self, label='', validators=None, coerce=str, **kwargs):
        self.coerce = coerce
        super().__init__(label, validators, **kwargs)

    def process_formdata(self, valuelist):
        super().process_formdata(valuelist)
        self.data = [self.coerce(i) for i in valuelist or []]


def is_dict_validator(form, field):
    if not isinstance(field.data, dict):
        raise ValidationError('Field "%s" must be dictionary' % field.name)


class DjangoTranslations:
    def gettext(self, string):
        return ugettext(string)

    def ngettext(self, singular, plural, n):
        return ungettext(singular, plural, n)


class I18NForm(Form):
    _django_tranlations = DjangoTranslations()

    def _get_translations(self):
        return self._django_tranlations


class ApiArtefactForm(I18NForm):
    """ Форма апи для артефактов ревизий: групповых атрибутов
    и фасетов.
    """
    revision = IntegerField('revision', [DataRequired(message=required_message)])
    name = StringField('name')
    values = ListField('values')
    language = StringField('language', [DataRequired(message=required_message)])

    def get_storage(self, name):
        repository = storages.StorageRepository()
        try:
            revision = repository['revision'].get(self.revision.data)
        except ObjectDoesNotExist:
            revision = None

        return storages.ArtefactStorageRepository(revision)[name]


class ApiUserForm(I18NForm):
    user = StringField('user', [DataRequired(message=required_message)])
    groups = SplitField('groups')
    features = MaskField('feature', 'Фичи')


class ApiRevisionForm(ApiUserForm):
    organization = StringField('organization', [DataRequired(message=required_message)])


class ApiOrganizationForm(I18NForm):
    organization = StringField('organization', [DataRequired(message=required_message)])


class ApiDirectoryEventForm(I18NForm):
    org_id = IntegerField('org_id', [DataRequired(message=required_message)])
    event = StringField('event', [DataRequired(message=required_message)])
    revision = IntegerField('revision', default=0)
    object = Field('object', [is_dict_validator])


class ApiDirectorySyncForm(I18NForm):
    org_id = IntegerField('org_id', [DataRequired(message=required_message)])


class SearchApiMarkForm(I18NForm):
    """
    Форма оценки релевантности документа в поисковой выдаче
    """
    request_id = StringField('request_id', [DataRequired(message=required_message)])
    url = StringField('url', [DataRequired(message=required_message), URL(message=url_message)])
    href = StringField('href', default='')
    text = StringField('text', default='')
    scope = SelectField(
        label='scope',
        choices=Mark.SEARCH_SCOPES,
        validators=[
            DataRequired(message=required_message),
        ],
    )
    layer = StringField(
        label='layer',
        validators=[
            DataRequired(message=required_message),
        ],
    )
    score = SelectField(
        label='score',
        choices=Mark.SCORE_CHOICES,
        validators=[
            DataRequired(message=required_message),
        ],
    )
    position = IntegerField('position', default=-1)
    mode = SelectField(
        label='mode',
        choices=Mark.MODES,
        default='search',
    )
    uid = StringField(
        label='uid',
    )
    wizard_id = StringField('wizard_id', default='')


class SuggestApiMarkForm(I18NForm):
    """
    Форма оценки релевантности документа в выдаче саджеста
    """
    url = StringField('url', [DataRequired(message=required_message), URL(message=url_message)])
    href = StringField('href', [DataRequired(message=required_message), URL(message=url_message)])
    text = StringField('text')
    scope = SelectField(
        label='scope',
        choices=Mark.SUGGEST_SCOPES,
        validators=[
            DataRequired(message=required_message),
        ],
    )
    layer = StringField(
        label='layer',
        validators=[
            DataRequired(message=required_message),
        ],
    )
    score = SelectField(
        label='score',
        choices=Mark.SUGGEST_SCORE_CHOICES,
        validators=[
            DataRequired(message=required_message),
        ],
    )
    position = IntegerField('position')
    mode = SelectField(
        label='mode',
        choices=Mark.MODES,
        validators=[DataRequired(message=required_message)]
    )
    uid = StringField(
        label='uid',
    )


class SuggestAnswerForm(I18NForm):
    """
    Форма предложения правильного документа для запроса в поисковой выдаче
    """
    request_id = StringField('request_id', [DataRequired(message=required_message)])
    url = URLField('url', [DataRequired(message=required_message), MaybeSchemalessURL(message=url_message)])
    scope = SelectField(
        label='scope',
        choices=scope_names,
        validators=[DataRequired()]
    )
    search_text = StringField('search_text', [DataRequired(message=required_message)])

    class Meta:
        locales = ['en', 'ru']
