from django import forms
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.gis.geos import Point
from django.forms.utils import ErrorList
from django.template.defaultfilters import slugify

from .models import DataLayer, Map, Team

DEFAULT_LATITUDE = (
    settings.LEAFLET_LATITUDE if hasattr(settings, "LEAFLET_LATITUDE") else 51
)
DEFAULT_LONGITUDE = (
    settings.LEAFLET_LONGITUDE if hasattr(settings, "LEAFLET_LONGITUDE") else 2
)
DEFAULT_CENTER = Point(DEFAULT_LONGITUDE, DEFAULT_LATITUDE)

User = get_user_model()


class FlatErrorList(ErrorList):
    def __unicode__(self):
        return self.flat()

    def flat(self):
        if not self:
            return ""
        return " — ".join([e for e in self])


class SendLinkForm(forms.Form):
    email = forms.EmailField()


class UpdateMapPermissionsForm(forms.ModelForm):
    class Meta:
        model = Map
        fields = ("edit_status", "editors", "share_status", "owner", "team")


class AnonymousMapPermissionsForm(forms.ModelForm):
    edit_status = forms.ChoiceField(choices=Map.ANONYMOUS_EDIT_STATUS)
    share_status = forms.ChoiceField(choices=Map.ANONYMOUS_SHARE_STATUS)

    class Meta:
        model = Map
        fields = ("edit_status", "share_status")


class DataLayerForm(forms.ModelForm):
    class Meta:
        model = DataLayer
        fields = ("geojson", "name", "display_on_load", "rank", "settings")


class DataLayerPermissionsForm(forms.ModelForm):
    class Meta:
        model = DataLayer
        fields = ("edit_status",)


class AnonymousDataLayerPermissionsForm(forms.ModelForm):
    edit_status = forms.ChoiceField(choices=DataLayer.ANONYMOUS_EDIT_STATUS)

    class Meta:
        model = DataLayer
        fields = ("edit_status",)


class MapSettingsForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MapSettingsForm, self).__init__(*args, **kwargs)
        self.fields["slug"].required = False
        self.fields["center"].widget.map_srid = 4326

    def clean_slug(self):
        slug = self.cleaned_data.get("slug", None)
        name = self.cleaned_data.get("name", None)
        if not slug and name:
            # If name is empty, don't do nothing, validation will raise
            # later on the process because name is required
            self.cleaned_data["slug"] = slugify(name) or "map"
            return self.cleaned_data["slug"][:50]
        else:
            return ""

    def clean_center(self):
        if not self.cleaned_data["center"]:
            point = DEFAULT_CENTER
            self.cleaned_data["center"] = point
        return self.cleaned_data["center"]

    class Meta:
        fields = ("settings", "name", "center", "slug", "tags")
        model = Map


class UserProfileForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ("username", "first_name", "last_name")


class TeamMembersField(forms.ModelMultipleChoiceField):
    def set_choices(self, choices):
        iterator = self.iterator(self)
        # Override queryset so to expose only selected choices:
        # - we don't want a select with 100000 options
        # - the select values will be used by the autocomplete widget to display
        #   already existing members of the team
        iterator.queryset = choices
        self.choices = iterator


class TeamForm(forms.ModelForm):
    class Meta:
        model = Team
        fields = ["name", "description", "members"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["members"].set_choices(self.initial["members"])
        self.fields["members"].widget.attrs["hidden"] = "hidden"

    members = TeamMembersField(queryset=User.objects.all())
