from __future__ import absolute_import, unicode_literals

import logging
import os

from django import forms
from django.template.defaultfilters import filesizeformat
from django.utils.translation import ugettext_lazy as _

from mayan.apps.acls.models import AccessControlList
from mayan.apps.common.forms import DetailForm

from .fields import (
    DocumentField, DocumentPageField, DocumentVersionField
)
from .models import (
    Document, DocumentType, DocumentTypeFilename
)
from .literals import DEFAULT_ZIP_FILENAME, PAGE_RANGE_ALL, PAGE_RANGE_CHOICES
from .permissions import permission_document_create
from .runtime import language_choices

logger = logging.getLogger(__name__)

# Document page forms


class DocumentPageForm(forms.Form):
    document_page = DocumentPageField()

    def __init__(self, *args, **kwargs):
        instance = kwargs.pop('instance', None)
        rotation = kwargs.pop('rotation', None)
        zoom = kwargs.pop('zoom', None)
        super(DocumentPageForm, self).__init__(*args, **kwargs)
        self.fields['document_page'].initial = instance
        self.fields['document_page'].widget.attrs.update({
            'zoom': zoom,
            'rotation': rotation,
        })


# Document forms
class DocumentPreviewForm(forms.Form):
    document = DocumentField()

    def __init__(self, *args, **kwargs):
        document = kwargs.pop('instance', None)
        super(DocumentPreviewForm, self).__init__(*args, **kwargs)
        self.fields['document'].initial = document


class DocumentVersionPreviewForm(forms.Form):
    document_version = DocumentVersionField()

    def __init__(self, *args, **kwargs):
        document_version = kwargs.pop('instance', None)
        super(DocumentVersionPreviewForm, self).__init__(*args, **kwargs)
        self.fields['document_version'].initial = document_version


class DocumentForm(forms.ModelForm):
    """
    Form sub classes from DocumentForm used only when editing a document
    """
    class Meta:
        fields = ('label', 'description', 'language')
        model = Document
        widgets = {
            'language': forms.Select(
                choices=language_choices, attrs={
                    'class': 'select2'
                }
            )

        }

    def __init__(self, *args, **kwargs):
        document_type = kwargs.pop('document_type', None)

        super(DocumentForm, self).__init__(*args, **kwargs)

        # Is a document (documents app edit) and has been saved (sources
        # app upload)?
        if self.instance and self.instance.pk:
            document_type = self.instance.document_type

        filenames_queryset = document_type.filenames.filter(enabled=True)

        if filenames_queryset:
            self.fields[
                'document_type_available_filenames'
            ] = forms.ModelChoiceField(
                queryset=filenames_queryset,
                required=False,
                label=_('Quick document rename'),
                widget=forms.Select(
                    attrs={
                        'class': 'select2'
                    }
                )
            )
            self.fields['preserve_extension'] = forms.BooleanField(
                label=_('Preserve extension'), required=False,
                help_text=_(
                    'Takes the file extension and moves it to the end of the '
                    'filename allowing operating systems that rely on file '
                    'extensions to open document correctly.'
                )
            )

    def clean(self):
        self.cleaned_data['label'] = self.get_final_label(
            # Fallback to the instance label if there is no label key or
            # there is a label key and is an empty string
            filename=self.cleaned_data.get('label') or self.instance.label
        )

        return self.cleaned_data

    def get_final_label(self, filename):
        if 'document_type_available_filenames' in self.cleaned_data:
            if self.cleaned_data['document_type_available_filenames']:
                if self.cleaned_data['preserve_extension']:
                    filename, extension = os.path.splitext(filename)

                    filename = '{}{}'.format(
                        self.cleaned_data[
                            'document_type_available_filenames'
                        ].filename, extension
                    )
                else:
                    filename = self.cleaned_data[
                        'document_type_available_filenames'
                    ].filename

        return filename


class DocumentPropertiesForm(DetailForm):
    """
    Detail class form to display a document file based properties
    """
    def __init__(self, *args, **kwargs):
        document = kwargs['instance']

        extra_fields = [
            {
                'label': _('Date added'),
                'field': 'date_added',
                'widget': forms.widgets.DateTimeInput
            },
            {'label': _('UUID'), 'field': 'uuid'},
            {
                'label': _('Language'),
                'field': lambda x: dict(language_choices).get(
                    document.language, _('Unknown')
                )
            },
        ]

        if document.latest_version:
            extra_fields += (
                {
                    'label': _('File mimetype'),
                    'field': lambda x: document.file_mimetype or _('None')
                },
                {
                    'label': _('File encoding'),
                    'field': lambda x: document.file_mime_encoding or _(
                        'None'
                    )
                },
                {
                    'label': _('File size'),
                    'field': lambda document: filesizeformat(
                        document.size
                    ) if document.size else '-'
                },
                {'label': _('Exists in storage'), 'field': 'exists'},
                {
                    'label': _('File path in storage'),
                    'field': 'latest_version.file'
                },
                {'label': _('Checksum'), 'field': 'checksum'},
                {'label': _('Pages'), 'field': 'page_count'},
            )

        kwargs['extra_fields'] = extra_fields
        super(DocumentPropertiesForm, self).__init__(*args, **kwargs)

    class Meta:
        fields = ('document_type', 'description')
        model = Document


class DocumentTypeSelectForm(forms.Form):
    """
    Form to select the document type of a document to be created, used
    as form #1 in the document creation wizard
    """
    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user', None)
        logger.debug('user: %s', user)
        super(DocumentTypeSelectForm, self).__init__(*args, **kwargs)

        queryset = AccessControlList.objects.filter_by_access(
            permission_document_create, user,
            queryset=DocumentType.objects.all()
        )

        self.fields['document_type'] = forms.ModelChoiceField(
            empty_label=None, label=_('Document type'), queryset=queryset,
            required=True, widget=forms.widgets.Select(attrs={'size': 10})
        )


class DocumentTypeFilenameForm_create(forms.ModelForm):
    """
    Model class form to create a new document type filename
    """
    class Meta:
        fields = ('filename',)
        model = DocumentTypeFilename


class DocumentDownloadForm(forms.Form):
    compressed = forms.BooleanField(
        label=_('Compress'), required=False,
        help_text=_(
            'Download the document in the original format or in a compressed '
            'manner. This option is selectable only when downloading one '
            'document, for multiple documents, the bundle will always be '
            'downloads as a compressed file.'
        )
    )
    zip_filename = forms.CharField(
        initial=DEFAULT_ZIP_FILENAME, label=_('Compressed filename'),
        required=False,
        help_text=_(
            'The filename of the compressed file that will contain the '
            'documents to be downloaded, if the previous option is selected.'
        )
    )

    def __init__(self, *args, **kwargs):
        self.queryset = kwargs.pop('queryset', None)
        super(DocumentDownloadForm, self).__init__(*args, **kwargs)
        if self.queryset.count() > 1:
            self.fields['compressed'].initial = True
            self.fields['compressed'].widget.attrs.update({'disabled': True})


class DocumentVersionDownloadForm(DocumentDownloadForm):
    preserve_extension = forms.BooleanField(
        label=_('Preserve extension'), required=False,
        help_text=_(
            'Takes the file extension and moves it to the end of the '
            'filename allowing operating systems that rely on file '
            'extensions to open the downloaded document version correctly.'
        )
    )


class DocumentPrintForm(forms.Form):
    page_group = forms.ChoiceField(
        choices=PAGE_RANGE_CHOICES, initial=PAGE_RANGE_ALL,
        widget=forms.RadioSelect
    )
    page_range = forms.CharField(label=_('Page range'), required=False)


class DocumentPageNumberForm(forms.Form):
    page = forms.ModelChoiceField(
        help_text=_(
            'Page number from which all the transformation will be cloned. '
            'Existing transformations will be lost.'
        ), queryset=None
    )

    def __init__(self, *args, **kwargs):
        self.document = kwargs.pop('document')
        super(DocumentPageNumberForm, self).__init__(*args, **kwargs)
        self.fields['page'].queryset = self.document.pages.all()
