
from datetime import datetime
from os.path import join
from uuid import uuid4

from django import forms
from django.core.files.storage import FileSystemStorage
from django.utils.importlib import import_module

from mezzanine.forms.models import FormEntry
from mezzanine.forms.settings import FIELD_MAX_LENGTH, UPLOAD_ROOT


fs = FileSystemStorage(location=UPLOAD_ROOT)


class FormForForm(forms.ModelForm):

    class Meta:
        model = FormEntry
        exclude = ("form", "entry_time")

    def __init__(self, form, *args, **kwargs):
        """
        Dynamically add each of the form fields for the given form model
        instance and its related field model instances.
        """
        self.form = form
        self.form_fields = form.fields.visible()
        super(FormForForm, self).__init__(*args, **kwargs)
        for field in self.form_fields:
            field_key = "field_%s" % field.id
            if "/" in field.field_type:
                field_class_name, field_widget = field.field_type.split("/")
            else:
                field_class_name, field_widget = field.field_type, None
            field_class = getattr(forms, field_class_name)
            field_args = {"label": field.label, "required": field.required,
                "help_text": field.help_text}
            arg_names = field_class.__init__.im_func.func_code.co_varnames
            if "max_length" in arg_names:
                field_args["max_length"] = FIELD_MAX_LENGTH
            if "choices" in arg_names:
                choices = field.choices.split(",")
                field_args["choices"] = zip(choices, choices)
            if field_widget is not None:
                module, widget = field_widget.rsplit(".", 1)
                field_args["widget"] = getattr(import_module(module), widget)
            self.initial[field_key] = field.default
            self.fields[field_key] = field_class(**field_args)
            # Add identifying CSS classes to the field.
            css_class = field_class_name.lower()
            if field.required:
                css_class += " required"
            self.fields[field_key].widget.attrs["class"] = css_class

    def save(self, **kwargs):
        """
        Create a FormEntry instance and related FieldEntry instances for each
        form field.
        """
        entry = super(FormForForm, self).save(commit=False)
        entry.form = self.form
        entry.entry_time = datetime.now()
        entry.save()
        for field in self.form_fields:
            field_key = "field_%s" % field.id
            value = self.cleaned_data[field_key]
            if value and self.fields[field_key].widget.needs_multipart_form:
                value = fs.save(join("forms", str(uuid4()), value.name), value)
            if isinstance(value, list):
                value = ", ".join([v.strip() for v in value])
            if value:
                entry.fields.create(field_id=field.id, value=value)
        return entry

    def email_to(self):
        """
        Return the value entered for the first field of type EmailField.
        """
        for field in self.form_fields:
            field_class = field.field_type.split("/")[0]
            if field_class == "EmailField":
                return self.cleaned_data["field_%s" % field.id]
        return None
