import django.contrib.admin as admin
from django.utils.translation import ugettext as _
from django.contrib.auth import admin as auth_admin, models as auth_models
from django.conf.urls.defaults import patterns
from django.core.urlresolvers import reverse, NoReverseMatch
import thread
import django_journal.admin

from . import models
from . import forms
from . import views
from . import notification
from . import actions


class DocbowAdminSite(admin.AdminSite):
    pass


site = DocbowAdminSite('docbow_admin')
site.disable_action('delete_selected')

class DocumentAdmin(admin.ModelAdmin):
    list_display = [ 'date', 'sender', 'recipients', 'filetype', 'filename_links', 'comment' ]
    list_filter = [ 'sender', 'to_user', 'to_list', 'filetype' ]
    fields = [ 'date', 'sender', 'recipients', 'filetype', 'filename_links', 'comment']
    readonly_fields = [ 'sender', 'filetype', 'date', 'recipients', 'filename_links', 'comment' ]
    filter_horizontal = [ 'to_user', 'to_list' ]
    date_hierarchy = 'date'


class SendingLimitationAdmin(admin.ModelAdmin):
    list_display = [ 'mailing_list', 'filetypes_list', 'lists_list'  ]
    filter_horizontal = [ 'filetypes', 'lists' ]
    actions = [ actions.export_as_csv, 'delete_selected' ]

    def lists_list(self, obj):
        '''Display method for the field lists'''
        return ', '.join(obj.lists.values_list('name', flat=True))
    lists_list.short_description = _('Limitation des destinataires')

    def filetypes_list(self, obj):
        '''Display method for the field filetypes'''
        return ', '.join(obj.filetypes.values_list('name', flat=True))
    filetypes_list.short_description = _('Limitation des types de fichier')


class MailingListAdmin(admin.ModelAdmin):
    list_display = [ 'name', 'is_active' ]
    list_filter = [ 'is_active' ]
    search_fields = [ 'name', 'members__username', 'members__first_name',
            'members__last_name' ]
    ordering = ['name']
    form = forms.MailingListForm
    actions = [ actions.export_as_csv ]

    def get_actions(self, request):
        a = super(MailingListAdmin, self).get_actions(request)
        if request.user.has_perm('docbow.delete_mailinglist'):
            a['delete_selected'] = self.get_action('delete_selected')
        if request.user.has_perm('docbow.change_mailinglist'):
            a['activate_selected'] = self.get_action(actions.activate_selected)
            a['deactivate_selected'] = self.get_action(actions.deactivate_selected)
        return a


class AttachedFileAdmin(admin.ModelAdmin):
    def get_model_perms(self, request):
        return {}

    def get_urls(self):
        urls = super(AttachedFileAdmin, self).get_urls()
        attached_file_urls = patterns('',
            (r'^(.+)/download/$', self.download)
        )
        return attached_file_urls + urls

    def download(self, request, object_id):
        '''Downlod view for attached files'''
        attached_file = models.AttachedFile.objects.get(pk=object_id)
        return views.upload(request, attached_file)


class DocbowUserAdmin(auth_admin.UserAdmin):
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (_('Permissions'), {'fields': ('is_active',)}),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
        (_('Groups'), {'fields': ('groups',)}),
    )
    readonly_fields = [ 'last_login', 'date_joined' ]
    exclude = [ 'user_permissions' ]
    actions = [ actions.export_as_csv ]
    list_display = auth_admin.UserAdmin.list_display + ( 'guest_account',
            'delegations', 'get_groups', 'get_lists', 'is_active')

    def get_groups(self, user):
        return u', '.join(group.name for group in user.groups.all())
    get_groups.short_description = _('groups')

    def get_lists(self, user):
        return u', '.join(_list.name for _list in user.mailing_lists.all())
    get_groups.short_description = _('mailing lists')

    def get_actions(self, request):
        a = super(DocbowUserAdmin, self).get_actions(request)
        if request.user.has_perm('auth.delete_docbowuser'):
            a['delete_selected'] = self.get_action('delete_selected')
        if request.user.has_perm('auth.change_docbowuser'):
            a['activate_selected'] = self.get_action(actions.activate_selected)
            a['deactivate_selected'] = self.get_action(actions.deactivate_selected)
        return a

    def guest_account(self, instance):
        try:
            return instance.docbowprofile.is_guest
        except models.DocbowProfile.DoesNotExist:
            return False
    guest_account.boolean = True
    guest_account.short_description = _('Guest account')

    def delegations(self, instance):
        from_users = auth_models.User.objects.filter(
                delegations_to__to=instance)
        return models.list_to_csv(from_users, models.username)
    delegations.short_description = _('Delegations by')

class DocbowGroupAdmin(auth_admin.GroupAdmin):
    exclude = [ 'permissions' ]


class MailboxAdmin(admin.ModelAdmin):
    list_display = [ 'owner', 'document', 'date', 'seen' ]
    list_filter = [ 'owner', 'outbox' ]

    def lookup_allowed(self, *args, **kwargs):
        '''Allow complex filters'''
        return True


class InboxAdmin(MailboxAdmin):
    list_display = [ 'date', 'owner', 'document', 'seen', 'deleted' ]
    fields = [ 'date', 'owner', 'document', 'seen', 'deleted' ]
    readonly_fields = [ 'date', 'owner', 'document', 'seen' ]

    def queryset(self, request):
        '''Only show input mailboxes'''
        qs = super(InboxAdmin, self).queryset(request)
        qs = qs.filter(outbox=False)
        return qs


class OutboxAdmin(MailboxAdmin):
    list_display = [ 'date', 'owner', 'document' ]
    fields = list_display
    readonly_fields = list_display

    def queryset(self, request):
        '''Only show output mailboxes'''
        qs = super(OutboxAdmin, self).queryset(request)
        qs = qs.filter(outbox=True)
        return qs


class ContentAdmin(admin.ModelAdmin):
    verbose_name = _('Predefined content description')
    actions = [ actions.export_as_csv, 'delete_selected' ]


class AutomaticForwardingAdmin(admin.ModelAdmin):
    filter_horizontal = [ 'filetypes', 'originaly_to_user', 'forward_to_user',
            'forward_to_list' ]
    form = forms.AutomaticForwardingForm
    actions = [ actions.export_as_csv, 'delete_selected' ]

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        if db_field.name in ('originaly_to_user', 'forward_to_user'):
            kwargs["queryset"] = models.non_guest_users()
        return super(AutomaticForwardingAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)


class FileTypeAttachedFileKindAdmin(admin.TabularInline):
    model = models.FileTypeAttachedFileKind
    sortable_field_name = 'position'
    extra = 0


class FileTypeAdmin(admin.ModelAdmin):
    list_display = [ 'name', 'is_active' ]
    actions = [ actions.export_as_csv ]
    inlines = [ FileTypeAttachedFileKindAdmin ]


class NotificationAdmin(admin.ModelAdmin):
    search_fields = ['user__username', 'user__first_name',
            'user__last_name', 'user__docbowprofile__mobile_phone']
    list_display = [ 'create_dt', '_document', 'user', 'kind', 'done', 'failure' ]
    readonly_fields = [ 'ctx' ]
    date_hierarchy = 'create_dt'
    list_filter = ['user', 'kind', 'done']
    actions = ['retry', 'delete_selected']

    def retry(self, request, queryset):
        queryset.update(done=False, failure=None)
        thread.start_new_thread(notification.process_notifications, ())
    retry.short_description = _('Clear failure and done field, resubmitting '
            'the notifications.')

    def object_link(self, obj):
        if obj is not None:
            url = u'{0}:{1}_{2}_change'.format(self.admin_site.name,
                    obj.__class__._meta.app_label,
                    obj.__class__._meta.module_name)
            try:
                url = reverse(url, args=(obj.id,))
                return u'<a href="{0}" class="external-link">{1}</a>'.format(url, obj)
            except NoReverseMatch:
                pass
        return ''

    def _document(self, notification):
        return self.object_link(notification.document)
    _document.short_description = _('Document')
    _document.allow_tags = True


class JournalAdmin(django_journal.admin.JournalAdmin):
    def user(self, entry):
        '''Search and return any associated objectdata whose tag is "user"'''
        user, delegate = '', ''
        for objectdata in entry.objectdata_set.all():
            if objectdata.tag.name == 'user':
                user = self.object_filter_link(objectdata) + \
                        self.object_link(objectdata)
            if objectdata.tag.name == 'delegate':
                delegate = self.object_filter_link(objectdata) + \
                        self.object_link(objectdata)
        if user and delegate:
            return delegate + _(' as ') + user
        elif user:
            return user
        return _('None')
    user.allow_tags = True
    user.short_description = _('User')


class DelegationAdmin(admin.ModelAdmin):
    list_display = [ 'id', 'by', 'to' ]


# Docbow Admin Site
site.register(auth_models.User, DocbowUserAdmin)
site.register(models.DocbowGroup, DocbowGroupAdmin)

site.register(models.FileType, FileTypeAdmin)
site.register(models.Content, ContentAdmin)
site.register(models.Document, DocumentAdmin)
site.register(models.MailingList, MailingListAdmin)
site.register(models.Delegation, DelegationAdmin)
site.register(models.Inbox, InboxAdmin)
site.register(models.Outbox, OutboxAdmin)
site.register(models.AttachedFile, AttachedFileAdmin)
site.register(models.SendingLimitation, SendingLimitationAdmin)
site.register(models.AutomaticForwarding, AutomaticForwardingAdmin)
site.register(models.Notification, NotificationAdmin)
_('Django_Journal')
_('Auth')
_('Docbow')
site.register(django_journal.admin.Journal, JournalAdmin)


# Superadmin Admin Site
admin.site.register(models.FileType)
admin.site.register(models.Content, ContentAdmin)
admin.site.register(models.Document)
admin.site.register(models.AttachedFile)
admin.site.register(models.MailingList, MailingListAdmin)
admin.site.register(models.Delegation, DelegationAdmin)
admin.site.register(models.Mailbox, MailboxAdmin)
admin.site.register(models.Notification, NotificationAdmin)
admin.site.register(models.DocbowProfile)
