# admin.py - PassiveTest Django Admin

from core.admin import ReadOnlyAwareAdmin, SliceInline
from core.middleware import get_request
from core.models import User

from django import forms
from django.contrib import admin

from services.passivetest.models import *

class PassiveTestForm(forms.ModelForm):

    class Meta:
        model = PassiveTestService
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(PassiveTestForm, self).__init__(*args, **kwargs)

        if self.instance:
            self.fields['tap_ports'].initial = self.instance.tap_ports
            self.fields['reset_viv'].initial = self.instance.reset_viv

    def save(self, commit=True):
        self.instance.tap_ports = self.cleaned_data.get('tap_ports')
        self.instance.reset_viv = self.cleaned_data.get('reset_viv')
        return super(PassiveTestForm, self).save(commit=commit)

class PassiveTestAdmin(ReadOnlyAwareAdmin):

    model = PassiveTestService
    verbose_name = PASSIVETEST_SERVICE_NAME_VERBOSE
    verbose_name_plural = PASSIVETEST_SERVICE_NAME_VERBOSE_PLURAL
    form = PassiveTestForm
    inlines = [SliceInline]

    list_display = ('backend_status_icon', 'name', 'tap_ports', 'reset_viv', 'enabled')
    list_display_links = ('backend_status_icon', 'name', 'tap_ports', 'reset_viv')

    fieldsets = [(None, {
        'fields': ['backend_status_text', 'name', 'enabled', 'versionNumber', 'tap_ports', 'reset_viv', 'description',],
        'classes':['suit-tab suit-tab-general',],
        })]

    readonly_fields = ('backend_status_text', )
    user_readonly_fields = ['name', 'enabled', 'versionNumber', 'description',]

    extracontext_registered_admins = True

    suit_form_tabs = (
        ('general', 'PassiveTest Details', ),
        ('slices', 'Slices',),
        )

    suit_form_includes = ((
        'top',
        'administration'),
        )

    def get_queryset(self, request):
        return PassiveTestService.get_service_objects_by_user(request.user)

admin.site.register(PassiveTestService, PassiveTestAdmin)

class PassiveTestTenantForm(forms.ModelForm):

    class Meta:
        model = PassiveTestTenant
        fields = '__all__'

    creator = forms.ModelChoiceField(queryset=User.objects.all())

    def __init__(self, *args, **kwargs):
        super(PassiveTestTenantForm, self).__init__(*args, **kwargs)

        self.fields['kind'].widget.attrs['readonly'] = True
        self.fields['kind'].initial = PASSIVETEST_KIND

        self.fields['provider_service'].queryset = PassiveTestService.get_service_objects().all()

        if self.instance:
            self.fields['creator'].initial = self.instance.creator

        if (not self.instance) or (not self.instance.pk):
            self.fields['creator'].initial = get_request().user
            if PassiveTestService.get_service_objects().exists():
                self.fields['provider_service'].initial = PassiveTestService.get_service_objects().all()[0]

    def save(self, commit=True):
        self.instance.creator = self.cleaned_data.get('creator')
        return super(PassiveTestTenantForm, self).save(commit=commit)


class PassiveTestTenantAdmin(ReadOnlyAwareAdmin):

    verbose_name = PASSIVETEST_TENANT_NAME_VERBOSE
    verbose_name_plural = PASSIVETEST_TENANT_NAME_VERBOSE_PLURAL

    list_display = ('id', 'backend_status_icon', 'instance')
    list_display_links = ('backend_status_icon', 'instance', 'id')

    fieldsets = [(None, {
        'fields': ['backend_status_text', 'kind', 'provider_service', 'instance', 'creator'],
        'classes': ['suit-tab suit-tab-general'],
        })]

    readonly_fields = ('backend_status_text', 'instance',)

    form = PassiveTestTenantForm

    suit_form_tabs = (('general', 'Details'),)

    def get_queryset(self, request):
        return PassiveTestTenant.get_tenant_objects_by_user(request.user)

admin.site.register(PassiveTestTenant, PassiveTestTenantAdmin)

