from django import forms
from django.utils.translation import gettext_lazy as _

from dcim.choices import *
from dcim.constants import *
from dcim.models import *
from extras.forms import LocalConfigContextFilterForm
from extras.models import ConfigTemplate
from ipam.models import ASN, VRF, VLANTranslationPolicy
from netbox.choices import *
from netbox.forms import (
    NestedGroupModelFilterSetForm,
    NetBoxModelFilterSetForm,
    OrganizationalModelFilterSetForm,
    PrimaryModelFilterSetForm,
)
from netbox.forms.mixins import OwnerFilterMixin
from tenancy.forms import ContactModelFilterForm, TenancyFilterForm
from tenancy.models import Tenant
from users.models import User
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice
from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, PositiveBigIntegerField, TagFilterField
from utilities.forms.rendering import FieldSet
from utilities.forms.widgets import NumberWithOptions
from virtualization.models import Cluster, ClusterGroup, VirtualMachine
from vpn.models import L2VPN
from wireless.choices import *

__all__ = (
    'CableBundleFilterForm',
    'CableFilterForm',
    'ConsoleConnectionFilterForm',
    'ConsolePortFilterForm',
    'ConsolePortTemplateFilterForm',
    'ConsoleServerPortFilterForm',
    'ConsoleServerPortTemplateFilterForm',
    'DeviceBayFilterForm',
    'DeviceBayTemplateFilterForm',
    'DeviceFilterForm',
    'DeviceRoleFilterForm',
    'DeviceTypeFilterForm',
    'FrontPortFilterForm',
    'FrontPortTemplateFilterForm',
    'InterfaceConnectionFilterForm',
    'InterfaceFilterForm',
    'InterfaceTemplateFilterForm',
    'InventoryItemFilterForm',
    'InventoryItemRoleFilterForm',
    'InventoryItemTemplateFilterForm',
    'LocationFilterForm',
    'MACAddressFilterForm',
    'ManufacturerFilterForm',
    'ModuleBayFilterForm',
    'ModuleBayTemplateFilterForm',
    'ModuleFilterForm',
    'ModuleTypeFilterForm',
    'ModuleTypeProfileFilterForm',
    'PlatformFilterForm',
    'PowerConnectionFilterForm',
    'PowerFeedFilterForm',
    'PowerOutletFilterForm',
    'PowerOutletTemplateFilterForm',
    'PowerPanelFilterForm',
    'PowerPortFilterForm',
    'PowerPortTemplateFilterForm',
    'RackElevationFilterForm',
    'RackFilterForm',
    'RackGroupFilterForm',
    'RackReservationFilterForm',
    'RackRoleFilterForm',
    'RackTypeFilterForm',
    'RearPortFilterForm',
    'RearPortTemplateFilterForm',
    'RegionFilterForm',
    'SiteFilterForm',
    'SiteGroupFilterForm',
    'VirtualChassisFilterForm',
    'VirtualDeviceContextFilterForm',
)


class DeviceComponentFilterForm(OwnerFilterMixin, NetBoxModelFilterSetForm):
    name = forms.CharField(
        label=_('Name'),
        required=False
    )
    label = forms.CharField(
        label=_('Label'),
        required=False
    )
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_group_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Site group')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id',
            'group_id': '$site_group_id',
        },
        label=_('Site')
    )
    location_id = DynamicModelMultipleChoiceField(
        queryset=Location.objects.all(),
        required=False,
        query_params={
            'site_id': '$site_id',
        },
        label=_('Location')
    )
    rack_id = DynamicModelMultipleChoiceField(
        queryset=Rack.objects.all(),
        required=False,
        query_params={
            'site_id': '$site_id',
            'location_id': '$location_id',
        },
        label=_('Rack')
    )
    virtual_chassis_id = DynamicModelMultipleChoiceField(
        queryset=VirtualChassis.objects.all(),
        required=False,
        label=_('Virtual Chassis')
    )
    device_type_id = DynamicModelMultipleChoiceField(
        queryset=DeviceType.objects.all(),
        required=False,
        label=_('Device type')
    )
    device_role_id = DynamicModelMultipleChoiceField(
        queryset=DeviceRole.objects.all(),
        required=False,
        label=_('Device role')
    )
    tenant_id = DynamicModelMultipleChoiceField(
        queryset=Tenant.objects.all(),
        required=False,
        label=_('Tenant')
    )
    device_id = DynamicModelMultipleChoiceField(
        queryset=Device.objects.all(),
        required=False,
        query_params={
            'site_id': '$site_id',
            'location_id': '$location_id',
            'virtual_chassis_id': '$virtual_chassis_id',
            'device_type_id': '$device_type_id',
            'role_id': '$role_id',
            'tenant_id': '$tenant_id'
        },
        label=_('Device')
    )
    device_status = forms.MultipleChoiceField(
        choices=DeviceStatusChoices,
        required=False,
        label=_('Device Status'),
    )


class RegionFilterForm(ContactModelFilterForm, NestedGroupModelFilterSetForm):
    model = Region
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('parent_id', name=_('Region')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
        FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts'))
    )
    parent_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Parent region')
    )
    tag = TagFilterField(model)


class SiteGroupFilterForm(ContactModelFilterForm, NestedGroupModelFilterSetForm):
    model = SiteGroup
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('parent_id', name=_('Site Group')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
        FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts'))
    )
    parent_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Parent group')
    )
    tag = TagFilterField(model)


class SiteFilterForm(TenancyFilterForm, ContactModelFilterForm, PrimaryModelFilterSetForm):
    model = Site
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('status', 'region_id', 'group_id', 'asn_id', name=_('Attributes')),
        FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
        FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
    )
    selector_fields = ('filter_id', 'q', 'region_id', 'group_id')
    status = forms.MultipleChoiceField(
        label=_('Status'),
        choices=SiteStatusChoices,
        required=False
    )
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    group_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Site group')
    )
    asn_id = DynamicModelMultipleChoiceField(
        queryset=ASN.objects.all(),
        required=False,
        label=_('ASNs')
    )
    tag = TagFilterField(model)


class LocationFilterForm(TenancyFilterForm, ContactModelFilterForm, NestedGroupModelFilterSetForm):
    model = Location
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('region_id', 'site_group_id', 'site_id', 'parent_id', 'status', 'facility', name=_('Attributes')),
        FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
        FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
    )
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_group_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Site group')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id',
            'group_id': '$site_group_id',
        },
        label=_('Site')
    )
    parent_id = DynamicModelMultipleChoiceField(
        queryset=Location.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id',
            'site_id': '$site_id',
        },
        label=_('Parent')
    )
    status = forms.MultipleChoiceField(
        label=_('Status'),
        choices=LocationStatusChoices,
        required=False
    )
    facility = forms.CharField(
        label=_('Facility'),
        required=False
    )
    tag = TagFilterField(model)


class RackGroupFilterForm(OrganizationalModelFilterSetForm):
    model = RackGroup
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    tag = TagFilterField(model)


class RackRoleFilterForm(OrganizationalModelFilterSetForm):
    model = RackRole
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    tag = TagFilterField(model)


class RackBaseFilterForm(PrimaryModelFilterSetForm):
    form_factor = forms.MultipleChoiceField(
        label=_('Form factor'),
        choices=RackFormFactorChoices,
        required=False
    )
    width = forms.MultipleChoiceField(
        label=_('Width'),
        choices=RackWidthChoices,
        required=False
    )
    u_height = forms.IntegerField(
        required=False,
        min_value=1
    )
    starting_unit = forms.IntegerField(
        required=False,
        min_value=1
    )
    desc_units = forms.NullBooleanField(
        required=False,
        label=_('Descending units'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    weight = forms.DecimalField(
        label=_('Weight'),
        required=False,
        min_value=1
    )
    max_weight = forms.IntegerField(
        label=_('Max weight'),
        required=False,
        min_value=1
    )
    weight_unit = forms.ChoiceField(
        label=_('Weight unit'),
        choices=add_blank_choice(WeightUnitChoices),
        required=False
    )


class RackTypeFilterForm(RackBaseFilterForm):
    model = RackType
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('manufacturer_id', 'form_factor', 'width', 'u_height', 'rack_count', name=_('Rack Type')),
        FieldSet('starting_unit', 'desc_units', name=_('Numbering')),
        FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    selector_fields = ('filter_id', 'q', 'manufacturer_id')
    manufacturer_id = DynamicModelMultipleChoiceField(
        queryset=Manufacturer.objects.all(),
        required=False,
        label=_('Manufacturer')
    )
    rack_count = forms.IntegerField(
        label=_('Rack count'),
        required=False,
        min_value=0,
    )
    tag = TagFilterField(model)


class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, RackBaseFilterForm):
    model = Rack
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'group_id', name=_('Location')),
        FieldSet('status', 'role_id', 'manufacturer_id', 'rack_type_id', 'serial', 'asset_tag', name=_('Rack')),
        FieldSet('form_factor', 'width', 'u_height', 'airflow', name=_('Hardware')),
        FieldSet('starting_unit', 'desc_units', name=_('Numbering')),
        FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')),
        FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
        FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
    )
    selector_fields = ('filter_id', 'q', 'region_id', 'site_group_id', 'site_id', 'location_id')
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id'
        },
        label=_('Site')
    )
    site_group_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Site group')
    )
    location_id = DynamicModelMultipleChoiceField(
        queryset=Location.objects.all(),
        required=False,
        null_option='None',
        query_params={
            'site_id': '$site_id'
        },
        label=_('Location')
    )
    group_id = DynamicModelMultipleChoiceField(
        queryset=RackGroup.objects.all(),
        required=False,
        null_option='None',
        label=_('Rack group')
    )
    status = forms.MultipleChoiceField(
        label=_('Status'),
        choices=RackStatusChoices,
        required=False
    )
    role_id = DynamicModelMultipleChoiceField(
        queryset=RackRole.objects.all(),
        required=False,
        null_option='None',
        label=_('Role')
    )
    manufacturer_id = DynamicModelMultipleChoiceField(
        queryset=Manufacturer.objects.all(),
        required=False,
        label=_('Manufacturer')
    )
    rack_type_id = DynamicModelMultipleChoiceField(
        queryset=RackType.objects.all(),
        required=False,
        query_params={
            'manufacturer_id': '$manufacturer_id'
        },
        label=_('Rack type')
    )
    airflow = forms.MultipleChoiceField(
        label=_('Airflow'),
        choices=add_blank_choice(RackAirflowChoices),
        required=False
    )
    serial = forms.CharField(
        label=_('Serial'),
        required=False
    )
    asset_tag = forms.CharField(
        label=_('Asset tag'),
        required=False
    )
    tag = TagFilterField(model)


class RackElevationFilterForm(RackFilterForm):
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'group_id', 'id', name=_('Location')),
        FieldSet('status', 'role_id', name=_('Function')),
        FieldSet('type', 'width', 'serial', 'asset_tag', name=_('Hardware')),
        FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')),
        FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
        FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
    )
    id = DynamicModelMultipleChoiceField(
        queryset=Rack.objects.all(),
        label=_('Rack'),
        required=False,
        query_params={
            'site_id': '$site_id',
            'location_id': '$location_id',
        }
    )


class RackReservationFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
    model = RackReservation
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('status', 'user_id', 'unit_count_min', 'unit_count_max', name=_('Reservation')),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'group_id', 'rack_id', name=_('Rack')),
        FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_group_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Site group')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id',
            'group_id': '$site_group_id',
        },
        label=_('Site')
    )
    location_id = DynamicModelMultipleChoiceField(
        queryset=Location.objects.all(),
        required=False,
        query_params={
            'site_id': '$site_id',
        },
        label=_('Location'),
        null_option='None'
    )
    group_id = DynamicModelMultipleChoiceField(
        queryset=RackGroup.objects.all(),
        required=False,
        null_option='None',
        label=_('Rack group')
    )
    rack_id = DynamicModelMultipleChoiceField(
        queryset=Rack.objects.all(),
        required=False,
        query_params={
            'group_id': '$group_id',
            'site_id': '$site_id',
            'location_id': '$location_id',
        },
        label=_('Rack')
    )
    status = forms.MultipleChoiceField(
        label=_('Status'),
        choices=RackReservationStatusChoices,
        required=False
    )
    user_id = DynamicModelMultipleChoiceField(
        queryset=User.objects.all(),
        required=False,
        label=_('User')
    )
    unit_count_min = forms.IntegerField(
        required=False,
        label=_("Minimum U's")
    )
    unit_count_max = forms.IntegerField(
        required=False,
        label=_("Maximum U's")
    )
    tag = TagFilterField(model)


class ManufacturerFilterForm(ContactModelFilterForm, OrganizationalModelFilterSetForm):
    model = Manufacturer
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
        FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts'))
    )
    tag = TagFilterField(model)


class DeviceTypeFilterForm(PrimaryModelFilterSetForm):
    model = DeviceType
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet(
            'manufacturer_id', 'default_platform_id', 'part_number', 'device_count',
            'subdevice_role', 'airflow', name=_('Hardware')
        ),
        FieldSet('has_front_image', 'has_rear_image', name=_('Images')),
        FieldSet(
            'console_ports', 'console_server_ports', 'power_ports', 'power_outlets', 'interfaces',
            'pass_through_ports', 'device_bays', 'module_bays', 'inventory_items', name=_('Components')
        ),
        FieldSet('weight', 'weight_unit', name=_('Weight')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    selector_fields = ('filter_id', 'q', 'manufacturer_id')
    manufacturer_id = DynamicModelMultipleChoiceField(
        queryset=Manufacturer.objects.all(),
        required=False,
        label=_('Manufacturer')
    )
    default_platform_id = DynamicModelMultipleChoiceField(
        queryset=Platform.objects.all(),
        required=False,
        label=_('Default platform')
    )
    part_number = forms.CharField(
        label=_('Part number'),
        required=False
    )
    device_count = forms.IntegerField(
        label=_('Device count'),
        required=False,
        min_value=0,
    )
    subdevice_role = forms.MultipleChoiceField(
        label=_('Subdevice role'),
        choices=add_blank_choice(SubdeviceRoleChoices),
        required=False
    )
    airflow = forms.MultipleChoiceField(
        label=_('Airflow'),
        choices=add_blank_choice(DeviceAirflowChoices),
        required=False
    )
    has_front_image = forms.NullBooleanField(
        required=False,
        label=_('Has a front image'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    has_rear_image = forms.NullBooleanField(
        required=False,
        label=_('Has a rear image'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    console_ports = forms.NullBooleanField(
        required=False,
        label=_('Has console ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    console_server_ports = forms.NullBooleanField(
        required=False,
        label=_('Has console server ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    power_ports = forms.NullBooleanField(
        required=False,
        label=_('Has power ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    power_outlets = forms.NullBooleanField(
        required=False,
        label=_('Has power outlets'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    interfaces = forms.NullBooleanField(
        required=False,
        label=_('Has interfaces'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    pass_through_ports = forms.NullBooleanField(
        required=False,
        label=_('Has pass-through ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    device_bays = forms.NullBooleanField(
        required=False,
        label=_('Has device bays'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    module_bays = forms.NullBooleanField(
        required=False,
        label=_('Has module bays'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    inventory_items = forms.NullBooleanField(
        required=False,
        label=_('Has inventory items'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    tag = TagFilterField(model)
    weight = forms.DecimalField(
        label=_('Weight'),
        required=False
    )
    weight_unit = forms.ChoiceField(
        label=_('Weight unit'),
        choices=add_blank_choice(WeightUnitChoices),
        required=False
    )


class ModuleTypeProfileFilterForm(PrimaryModelFilterSetForm):
    model = ModuleTypeProfile
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    selector_fields = ('filter_id', 'q')
    tag = TagFilterField(model)


class ModuleTypeFilterForm(PrimaryModelFilterSetForm):
    model = ModuleType
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet(
            'profile_id', 'manufacturer_id', 'part_number', 'module_count',
            'airflow', name=_('Hardware')
        ),
        FieldSet(
            'console_ports', 'console_server_ports', 'power_ports', 'power_outlets', 'interfaces',
            'pass_through_ports', 'module_bays', name=_('Components')
        ),
        FieldSet('weight', 'weight_unit', name=_('Weight')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    selector_fields = ('filter_id', 'q', 'manufacturer_id')
    profile_id = DynamicModelMultipleChoiceField(
        queryset=ModuleTypeProfile.objects.all(),
        required=False,
        null_option='None',
        label=_('Profile')
    )
    manufacturer_id = DynamicModelMultipleChoiceField(
        queryset=Manufacturer.objects.all(),
        required=False,
        label=_('Manufacturer')
    )
    part_number = forms.CharField(
        label=_('Part number'),
        required=False
    )
    module_count = forms.IntegerField(
        label=_('Module count'),
        required=False,
        min_value=0,
    )
    console_ports = forms.NullBooleanField(
        required=False,
        label=_('Has console ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    console_server_ports = forms.NullBooleanField(
        required=False,
        label=_('Has console server ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    power_ports = forms.NullBooleanField(
        required=False,
        label=_('Has power ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    power_outlets = forms.NullBooleanField(
        required=False,
        label=_('Has power outlets'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    interfaces = forms.NullBooleanField(
        required=False,
        label=_('Has interfaces'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    pass_through_ports = forms.NullBooleanField(
        required=False,
        label=_('Has pass-through ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    module_bays = forms.NullBooleanField(
        required=False,
        label=_('Has module bays'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    tag = TagFilterField(model)
    airflow = forms.MultipleChoiceField(
        label=_('Airflow'),
        choices=add_blank_choice(ModuleAirflowChoices),
        required=False
    )
    weight = forms.DecimalField(
        label=_('Weight'),
        required=False
    )
    weight_unit = forms.ChoiceField(
        label=_('Weight unit'),
        choices=add_blank_choice(WeightUnitChoices),
        required=False
    )


class DeviceRoleFilterForm(NestedGroupModelFilterSetForm):
    model = DeviceRole
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('parent_id', 'config_template_id', name=_('Device Role')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    config_template_id = DynamicModelMultipleChoiceField(
        queryset=ConfigTemplate.objects.all(),
        required=False,
        label=_('Config template')
    )
    parent_id = DynamicModelMultipleChoiceField(
        queryset=DeviceRole.objects.all(),
        required=False,
        label=_('Parent')
    )
    tag = TagFilterField(model)


class PlatformFilterForm(NestedGroupModelFilterSetForm):
    model = Platform
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('manufacturer_id', 'parent_id', 'config_template_id', name=_('Platform')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    selector_fields = ('filter_id', 'q', 'manufacturer_id')
    parent_id = DynamicModelMultipleChoiceField(
        queryset=Platform.objects.all(),
        required=False,
        label=_('Parent')
    )
    manufacturer_id = DynamicModelMultipleChoiceField(
        queryset=Manufacturer.objects.all(),
        required=False,
        label=_('Manufacturer')
    )
    config_template_id = DynamicModelMultipleChoiceField(
        queryset=ConfigTemplate.objects.all(),
        required=False,
        label=_('Config template')
    )
    tag = TagFilterField(model)


class DeviceFilterForm(
    LocalConfigContextFilterForm,
    TenancyFilterForm,
    ContactModelFilterForm,
    PrimaryModelFilterSetForm
):
    model = Device
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
        FieldSet('status', 'role_id', 'airflow', 'serial', 'asset_tag', 'mac_address', name=_('Operation')),
        FieldSet('manufacturer_id', 'device_type_id', 'platform_id', name=_('Hardware')),
        FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
        FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
        FieldSet(
            'console_ports', 'console_server_ports', 'power_ports', 'power_outlets', 'interfaces', 'pass_through_ports',
            name=_('Components')
        ),
        FieldSet('cluster_group_id', 'cluster_id', name=_('Cluster')),
        FieldSet(
            'has_primary_ip', 'has_oob_ip', 'virtual_chassis_member', 'config_template_id', 'local_context_data',
            'has_virtual_device_context',
            name=_('Miscellaneous')
        )
    )
    selector_fields = ('filter_id', 'q', 'region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id')
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_group_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Site group')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id',
            'group_id': '$site_group_id',
        },
        label=_('Site')
    )
    location_id = DynamicModelMultipleChoiceField(
        queryset=Location.objects.all(),
        required=False,
        null_option='None',
        query_params={
            'site_id': '$site_id'
        },
        label=_('Location')
    )
    rack_id = DynamicModelMultipleChoiceField(
        queryset=Rack.objects.all(),
        required=False,
        null_option='None',
        query_params={
            'site_id': '$site_id',
            'location_id': '$location_id',
        },
        label=_('Rack')
    )
    role_id = DynamicModelMultipleChoiceField(
        queryset=DeviceRole.objects.all(),
        required=False,
        label=_('Role')
    )
    manufacturer_id = DynamicModelMultipleChoiceField(
        queryset=Manufacturer.objects.all(),
        required=False,
        label=_('Manufacturer')
    )
    device_type_id = DynamicModelMultipleChoiceField(
        queryset=DeviceType.objects.all(),
        required=False,
        query_params={
            'manufacturer_id': '$manufacturer_id'
        },
        label=_('Model')
    )
    platform_id = DynamicModelMultipleChoiceField(
        queryset=Platform.objects.all(),
        required=False,
        null_option='None',
        label=_('Platform')
    )
    status = forms.MultipleChoiceField(
        label=_('Status'),
        choices=DeviceStatusChoices,
        required=False
    )
    airflow = forms.MultipleChoiceField(
        label=_('Airflow'),
        choices=add_blank_choice(DeviceAirflowChoices),
        required=False
    )
    serial = forms.CharField(
        label=_('Serial'),
        required=False
    )
    asset_tag = forms.CharField(
        label=_('Asset tag'),
        required=False
    )
    mac_address = forms.CharField(
        required=False,
        label=_('MAC address')
    )
    config_template_id = DynamicModelMultipleChoiceField(
        queryset=ConfigTemplate.objects.all(),
        required=False,
        label=_('Config template')
    )
    has_primary_ip = forms.NullBooleanField(
        required=False,
        label=_('Has a primary IP'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    has_oob_ip = forms.NullBooleanField(
        required=False,
        label=_('Has an OOB IP'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    virtual_chassis_member = forms.NullBooleanField(
        required=False,
        label=_('Virtual chassis member'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    console_ports = forms.NullBooleanField(
        required=False,
        label=_('Has console ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    console_server_ports = forms.NullBooleanField(
        required=False,
        label=_('Has console server ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    power_ports = forms.NullBooleanField(
        required=False,
        label=_('Has power ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    power_outlets = forms.NullBooleanField(
        required=False,
        label=_('Has power outlets'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    interfaces = forms.NullBooleanField(
        required=False,
        label=_('Has interfaces'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    pass_through_ports = forms.NullBooleanField(
        required=False,
        label=_('Has pass-through ports'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    has_virtual_device_context = forms.NullBooleanField(
        required=False,
        label=_('Has virtual device contexts'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    cluster_id = DynamicModelMultipleChoiceField(
        queryset=Cluster.objects.all(),
        required=False,
        label=_('Cluster')
    )
    cluster_group_id = DynamicModelMultipleChoiceField(
        queryset=ClusterGroup.objects.all(),
        required=False,
        label=_('Cluster group')
    )
    tag = TagFilterField(model)


class VirtualDeviceContextFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
    model = VirtualDeviceContext
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('device', 'status', 'has_primary_ip', name=_('Attributes')),
        FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    device = DynamicModelMultipleChoiceField(
        queryset=Device.objects.all(),
        required=False,
        label=_('Device')
    )
    status = forms.MultipleChoiceField(
        label=_('Status'),
        required=False,
        choices=add_blank_choice(VirtualDeviceContextStatusChoices)
    )
    has_primary_ip = forms.NullBooleanField(
        required=False,
        label=_('Has a primary IP'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    tag = TagFilterField(model)


class ModuleFilterForm(LocalConfigContextFilterForm, TenancyFilterForm, PrimaryModelFilterSetForm):
    model = Module
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', 'device_id', name=_('Location')),
        FieldSet(
            'profile_id', 'manufacturer_id', 'module_type_id', 'status', 'serial', 'asset_tag',
            name=_('Hardware')
        ),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    selector_fields = ('filter_id', 'q', 'manufacturer_id', 'profile_id')
    device_id = DynamicModelMultipleChoiceField(
        queryset=Device.objects.all(),
        required=False,
        query_params={
            'site_id': '$site_id',
            'location_id': '$location_id',
            'rack_id': '$rack_id',
        },
        label=_('Device')
    )
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_group_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Site group')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id',
            'group_id': '$site_group_id',
        },
        label=_('Site')
    )
    location_id = DynamicModelMultipleChoiceField(
        queryset=Location.objects.all(),
        required=False,
        query_params={
            'site_id': '$site_id',
        },
        label=_('Location')
    )
    rack_id = DynamicModelMultipleChoiceField(
        queryset=Rack.objects.all(),
        required=False,
        label=_('Rack'),
        null_option='None',
        query_params={
            'site_id': '$site_id',
            'location_id': '$location_id',
        }
    )
    manufacturer_id = DynamicModelMultipleChoiceField(
        queryset=Manufacturer.objects.all(),
        required=False,
        label=_('Manufacturer')
    )
    profile_id = DynamicModelMultipleChoiceField(
        queryset=ModuleTypeProfile.objects.all(),
        required=False,
        null_option='None',
        label=_('Profile')
    )
    module_type_id = DynamicModelMultipleChoiceField(
        queryset=ModuleType.objects.all(),
        required=False,
        query_params={
            'profile_id': '$profile_id',
            'manufacturer_id': '$manufacturer_id'
        },
        label=_('Type')
    )
    status = forms.MultipleChoiceField(
        label=_('Status'),
        choices=ModuleStatusChoices,
        required=False
    )
    serial = forms.CharField(
        label=_('Serial'),
        required=False
    )
    asset_tag = forms.CharField(
        label=_('Asset tag'),
        required=False
    )
    tag = TagFilterField(model)


class VirtualChassisFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
    model = VirtualChassis
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')),
        FieldSet('tenant_id', name=_('Tenant')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_group_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Site group')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id',
            'group_id': '$site_group_id',
        },
        label=_('Site')
    )
    tag = TagFilterField(model)


class CableBundleFilterForm(PrimaryModelFilterSetForm):
    model = CableBundle
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', name=_('Attributes')),
    )
    tag = TagFilterField(model)


class CableFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
    model = Cable
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('site_id', 'location_id', 'rack_id', 'device_id', name=_('Location')),
        FieldSet(
            'type', 'status', 'profile', 'color', 'length', 'length_unit', 'unterminated', 'bundle_id',
            name=_('Attributes'),
        ),
        FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id'
        },
        label=_('Site')
    )
    location_id = DynamicModelMultipleChoiceField(
        queryset=Location.objects.all(),
        required=False,
        label=_('Location'),
        null_option='None',
        query_params={
            'site_id': '$site_id'
        }
    )
    rack_id = DynamicModelMultipleChoiceField(
        queryset=Rack.objects.all(),
        required=False,
        label=_('Rack'),
        null_option='None',
        query_params={
            'site_id': '$site_id',
            'location_id': '$location_id',
        }
    )
    device_id = DynamicModelMultipleChoiceField(
        queryset=Device.objects.all(),
        required=False,
        query_params={
            'site_id': '$site_id',
            'location_id': '$location_id',
            'rack_id': '$rack_id',
            'tenant_id': '$tenant_id',
        },
        label=_('Device')
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=add_blank_choice(CableTypeChoices),
        required=False
    )
    status = forms.MultipleChoiceField(
        label=_('Status'),
        required=False,
        choices=add_blank_choice(LinkStatusChoices)
    )
    profile = forms.MultipleChoiceField(
        label=_('Profile'),
        required=False,
        choices=add_blank_choice(CableProfileChoices)
    )
    color = ColorField(
        label=_('Color'),
        required=False
    )
    length = forms.DecimalField(
        label=_('Length'),
        required=False,
    )
    length_unit = forms.ChoiceField(
        label=_('Length unit'),
        choices=add_blank_choice(CableLengthUnitChoices),
        required=False
    )
    unterminated = forms.NullBooleanField(
        label=_('Unterminated'),
        required=False,
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    bundle_id = DynamicModelMultipleChoiceField(
        queryset=CableBundle.objects.all(),
        required=False,
        label=_('Bundle'),
    )
    tag = TagFilterField(model)


class PowerPanelFilterForm(ContactModelFilterForm, PrimaryModelFilterSetForm):
    model = PowerPanel
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', name=_('Location')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
        FieldSet('contact', 'contact_role', 'contact_group', name=_('Contacts')),
    )
    selector_fields = ('filter_id', 'q', 'site_id', 'location_id')
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_group_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Site group')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id',
            'group_id': '$site_group_id',
        },
        label=_('Site')
    )
    location_id = DynamicModelMultipleChoiceField(
        queryset=Location.objects.all(),
        required=False,
        null_option='None',
        query_params={
            'site_id': '$site_id'
        },
        label=_('Location')
    )
    tag = TagFilterField(model)


class PowerFeedFilterForm(TenancyFilterForm, PrimaryModelFilterSetForm):
    model = PowerFeed
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('region_id', 'site_group_id', 'site_id', 'power_panel_id', 'rack_id', name=_('Location')),
        FieldSet('status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization', name=_('Attributes')),
        FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_group_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Site group')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id'
        },
        label=_('Site')
    )
    power_panel_id = DynamicModelMultipleChoiceField(
        queryset=PowerPanel.objects.all(),
        required=False,
        null_option='None',
        query_params={
            'site_id': '$site_id'
        },
        label=_('Power panel')
    )
    rack_id = DynamicModelMultipleChoiceField(
        queryset=Rack.objects.all(),
        required=False,
        null_option='None',
        query_params={
            'site_id': '$site_id'
        },
        label=_('Rack')
    )
    status = forms.MultipleChoiceField(
        label=_('Status'),
        choices=PowerFeedStatusChoices,
        required=False
    )
    type = forms.ChoiceField(
        label=_('Type'),
        choices=add_blank_choice(PowerFeedTypeChoices),
        required=False
    )
    supply = forms.ChoiceField(
        label=_('Supply'),
        choices=add_blank_choice(PowerFeedSupplyChoices),
        required=False
    )
    phase = forms.ChoiceField(
        label=_('Phase'),
        choices=add_blank_choice(PowerFeedPhaseChoices),
        required=False
    )
    voltage = forms.IntegerField(
        label=_('Voltage'),
        required=False
    )
    amperage = forms.IntegerField(
        label=_('Amperage'),
        required=False
    )
    max_utilization = forms.IntegerField(
        label=_('Max utilization'),
        required=False
    )
    tag = TagFilterField(model)


#
# Device components
#

class DeviceComponentTemplateFilterForm(NetBoxModelFilterSetForm):
    device_type_id = DynamicModelMultipleChoiceField(
        queryset=DeviceType.objects.all(),
        required=False,
        label=_('Device type'),
    )


class ModularDeviceComponentTemplateFilterForm(DeviceComponentTemplateFilterForm):
    module_type_id = DynamicModelMultipleChoiceField(
        queryset=ModuleType.objects.all(),
        required=False,
        query_params={'manufacturer_id': '$manufacturer_id'},
        label=_('Module Type'),
    )


class CabledFilterForm(forms.Form):
    cabled = forms.NullBooleanField(
        label=_('Cabled'),
        required=False,
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    occupied = forms.NullBooleanField(
        label=_('Occupied'),
        required=False,
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )


class PathEndpointFilterForm(CabledFilterForm):
    connected = forms.NullBooleanField(
        label=_('Connected'),
        required=False,
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )


class ConsolePortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
    model = ConsolePort
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', 'speed', name=_('Attributes')),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
        FieldSet(
            'tenant_id', 'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
            name=_('Device')
        ),
        FieldSet('cabled', 'connected', 'occupied', name=_('Connection')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=ConsolePortTypeChoices,
        required=False
    )
    speed = forms.MultipleChoiceField(
        label=_('Speed'),
        choices=ConsolePortSpeedChoices,
        required=False
    )
    tag = TagFilterField(model)


class ConsolePortTemplateFilterForm(ModularDeviceComponentTemplateFilterForm):
    model = ConsolePortTemplate
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', name=_('Attributes')),
        FieldSet('device_type_id', 'module_type_id', name=_('Device')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=ConsolePortTypeChoices,
        required=False
    )


class ConsoleServerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
    model = ConsoleServerPort
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', 'speed', name=_('Attributes')),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
        FieldSet(
            'tenant_id', 'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
            name=_('Device')
        ),
        FieldSet('cabled', 'connected', 'occupied', name=_('Connection')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=ConsolePortTypeChoices,
        required=False
    )
    speed = forms.MultipleChoiceField(
        label=_('Speed'),
        choices=ConsolePortSpeedChoices,
        required=False
    )
    tag = TagFilterField(model)


class ConsoleServerPortTemplateFilterForm(ModularDeviceComponentTemplateFilterForm):
    model = ConsoleServerPortTemplate
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', name=_('Attributes')),
        FieldSet('device_type_id', 'module_type_id', name=_('Device')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=ConsolePortTypeChoices,
        required=False
    )


class PowerPortFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
    model = PowerPort
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', name=_('Attributes')),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
        FieldSet(
            'tenant_id', 'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
            name=_('Device')
        ),
        FieldSet('cabled', 'connected', 'occupied', name=_('Connection')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=PowerPortTypeChoices,
        required=False
    )
    tag = TagFilterField(model)


class PowerPortTemplateFilterForm(ModularDeviceComponentTemplateFilterForm):
    model = PowerPortTemplate
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', name=_('Attributes')),
        FieldSet('device_type_id', 'module_type_id', name=_('Device')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=PowerPortTypeChoices,
        required=False
    )


class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
    model = PowerOutlet
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', 'color', 'status', name=_('Attributes')),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
        FieldSet(
            'tenant_id', 'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
            name=_('Device')
        ),
        FieldSet('cabled', 'connected', 'occupied', name=_('Connection')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=PowerOutletTypeChoices,
        required=False
    )
    tag = TagFilterField(model)
    color = ColorField(
        label=_('Color'),
        required=False
    )
    status = forms.MultipleChoiceField(
        label=_('Status'),
        choices=PowerOutletStatusChoices,
        required=False
    )


class PowerOutletTemplateFilterForm(ModularDeviceComponentTemplateFilterForm):
    model = PowerOutletTemplate
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', name=_('Attributes')),
        FieldSet('device_type_id', 'module_type_id', name=_('Device')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=PowerOutletTypeChoices,
        required=False
    )


class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
    model = Interface
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'kind', 'type', 'speed', 'duplex', 'enabled', 'mgmt_only', name=_('Attributes')),
        FieldSet('vrf_id', 'l2vpn_id', 'mac_address', 'wwn', name=_('Addressing')),
        FieldSet('poe_mode', 'poe_type', name=_('PoE')),
        FieldSet('mode', 'vlan_translation_policy_id', name=_('802.1Q Switching')),
        FieldSet('rf_role', 'rf_channel', 'rf_channel_width', 'tx_power', name=_('Wireless')),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
        FieldSet(
            'tenant_id', 'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
            'vdc_id',
            name=_('Device')
        ),
        FieldSet('cabled', 'connected', 'occupied', name=_('Connection')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    selector_fields = ('filter_id', 'q', 'device_id')
    vdc_id = DynamicModelMultipleChoiceField(
        queryset=VirtualDeviceContext.objects.all(),
        required=False,
        query_params={
            'device_id': '$device_id',
        },
        label=_('Virtual Device Context')
    )
    kind = forms.MultipleChoiceField(
        label=_('Kind'),
        choices=InterfaceKindChoices,
        required=False
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=InterfaceTypeChoices,
        required=False
    )
    speed = PositiveBigIntegerField(
        label=_('Speed'),
        required=False,
        widget=NumberWithOptions(
            options=InterfaceSpeedChoices
        )
    )
    duplex = forms.MultipleChoiceField(
        label=_('Duplex'),
        choices=InterfaceDuplexChoices,
        required=False
    )
    enabled = forms.NullBooleanField(
        label=_('Enabled'),
        required=False,
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    mgmt_only = forms.NullBooleanField(
        label=_('Mgmt only'),
        required=False,
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    mac_address = forms.CharField(
        required=False,
        label=_('MAC address')
    )
    wwn = forms.CharField(
        required=False,
        label=_('WWN')
    )
    poe_mode = forms.MultipleChoiceField(
        choices=InterfacePoEModeChoices,
        required=False,
        label=_('PoE mode')
    )
    poe_type = forms.MultipleChoiceField(
        choices=InterfacePoETypeChoices,
        required=False,
        label=_('PoE type')
    )
    mode = forms.MultipleChoiceField(
        choices=InterfaceModeChoices,
        required=False,
        label=_('802.1Q mode')
    )
    vlan_translation_policy_id = DynamicModelMultipleChoiceField(
        queryset=VLANTranslationPolicy.objects.all(),
        required=False,
        label=_('VLAN Translation Policy')
    )
    rf_role = forms.MultipleChoiceField(
        choices=WirelessRoleChoices,
        required=False,
        label=_('Wireless role')
    )
    rf_channel = forms.MultipleChoiceField(
        choices=WirelessChannelChoices,
        required=False,
        label=_('Wireless channel')
    )
    rf_channel_frequency = forms.IntegerField(
        required=False,
        label=_('Channel frequency (MHz)')
    )
    rf_channel_width = forms.IntegerField(
        required=False,
        label=_('Channel width (MHz)')
    )
    tx_power = forms.IntegerField(
        required=False,
        label=_('Transmit power (dBm)'),
        min_value=-40,
        max_value=127
    )
    vrf_id = DynamicModelMultipleChoiceField(
        queryset=VRF.objects.all(),
        required=False,
        label=_('VRF')
    )
    l2vpn_id = DynamicModelMultipleChoiceField(
        queryset=L2VPN.objects.all(),
        required=False,
        label=_('L2VPN')
    )
    tag = TagFilterField(model)


class InterfaceTemplateFilterForm(ModularDeviceComponentTemplateFilterForm):
    model = InterfaceTemplate
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', 'enabled', 'mgmt_only', name=_('Attributes')),
        FieldSet('poe_mode', 'poe_type', name=_('PoE')),
        FieldSet('rf_role', name=_('Wireless')),
        FieldSet('device_type_id', 'module_type_id', name=_('Device')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=InterfaceTypeChoices,
        required=False
    )
    enabled = forms.NullBooleanField(
        label=_('Enabled'),
        required=False,
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    mgmt_only = forms.NullBooleanField(
        label=_('Management only'),
        required=False,
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    poe_mode = forms.MultipleChoiceField(
        choices=InterfacePoEModeChoices,
        required=False,
        label=_('PoE mode')
    )
    poe_type = forms.MultipleChoiceField(
        choices=InterfacePoETypeChoices,
        required=False,
        label=_('PoE type')
    )
    rf_role = forms.MultipleChoiceField(
        choices=WirelessRoleChoices,
        required=False,
        label=_('Wireless role')
    )


class FrontPortFilterForm(CabledFilterForm, DeviceComponentFilterForm):
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', 'color', name=_('Attributes')),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
        FieldSet(
            'tenant_id', 'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
            name=_('Device')
        ),
        FieldSet('cabled', 'occupied', name=_('Cable')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    model = FrontPort
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=PortTypeChoices,
        required=False
    )
    color = ColorField(
        label=_('Color'),
        required=False
    )
    tag = TagFilterField(model)


class FrontPortTemplateFilterForm(ModularDeviceComponentTemplateFilterForm):
    model = FrontPortTemplate
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', 'color', name=_('Attributes')),
        FieldSet('device_type_id', 'module_type_id', name=_('Device')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=PortTypeChoices,
        required=False
    )
    color = ColorField(
        label=_('Color'),
        required=False
    )


class RearPortFilterForm(CabledFilterForm, DeviceComponentFilterForm):
    model = RearPort
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', 'color', name=_('Attributes')),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
        FieldSet(
            'tenant_id', 'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
            name=_('Device')
        ),
        FieldSet('cabled', 'occupied', name=_('Cable')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=PortTypeChoices,
        required=False
    )
    color = ColorField(
        label=_('Color'),
        required=False
    )
    tag = TagFilterField(model)


class RearPortTemplateFilterForm(ModularDeviceComponentTemplateFilterForm):
    model = RearPortTemplate
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'type', 'color', name=_('Attributes')),
        FieldSet('device_type_id', 'module_type_id', name=_('Device')),
    )
    type = forms.MultipleChoiceField(
        label=_('Type'),
        choices=PortTypeChoices,
        required=False
    )
    color = ColorField(
        label=_('Color'),
        required=False
    )


class ModuleBayFilterForm(DeviceComponentFilterForm):
    model = ModuleBay
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'position', 'enabled', name=_('Attributes')),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
        FieldSet(
            'tenant_id', 'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
            name=_('Device')
        ),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    position = forms.CharField(
        label=_('Position'),
        required=False
    )
    enabled = forms.NullBooleanField(
        label=_('Enabled'),
        required=False,
        widget=forms.Select(choices=BOOLEAN_WITH_BLANK_CHOICES),
    )
    tag = TagFilterField(model)


class ModuleBayTemplateFilterForm(ModularDeviceComponentTemplateFilterForm):
    model = ModuleBayTemplate
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'position', 'enabled', name=_('Attributes')),
        FieldSet('device_type_id', 'module_type_id', name=_('Device')),
    )
    position = forms.CharField(
        label=_('Position'),
        required=False,
    )
    enabled = forms.NullBooleanField(
        label=_('Enabled'),
        required=False,
        widget=forms.Select(choices=BOOLEAN_WITH_BLANK_CHOICES),
    )


class DeviceBayFilterForm(DeviceComponentFilterForm):
    model = DeviceBay
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'enabled', name=_('Attributes')),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
        FieldSet(
            'tenant_id', 'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
            name=_('Device')
        ),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    enabled = forms.NullBooleanField(
        label=_('Enabled'),
        required=False,
        widget=forms.Select(choices=BOOLEAN_WITH_BLANK_CHOICES),
    )
    tag = TagFilterField(model)


class DeviceBayTemplateFilterForm(DeviceComponentTemplateFilterForm):
    model = DeviceBayTemplate
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'enabled', name=_('Attributes')),
        FieldSet('device_type_id', name=_('Device')),
    )
    enabled = forms.NullBooleanField(
        label=_('Enabled'),
        required=False,
        widget=forms.Select(choices=BOOLEAN_WITH_BLANK_CHOICES),
    )


class InventoryItemFilterForm(DeviceComponentFilterForm):
    model = InventoryItem
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet(
            'name', 'label', 'status', 'role_id', 'manufacturer_id', 'serial', 'asset_tag', 'discovered',
            name=_('Attributes')
        ),
        FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
        FieldSet(
            'tenant_id', 'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
            name=_('Device')
        ),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    role_id = DynamicModelMultipleChoiceField(
        queryset=InventoryItemRole.objects.all(),
        required=False,
        label=_('Role')
    )
    manufacturer_id = DynamicModelMultipleChoiceField(
        queryset=Manufacturer.objects.all(),
        required=False,
        label=_('Manufacturer')
    )
    serial = forms.CharField(
        label=_('Serial'),
        required=False
    )
    asset_tag = forms.CharField(
        label=_('Asset tag'),
        required=False
    )
    discovered = forms.NullBooleanField(
        label=_('Discovered'),
        required=False,
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )
    status = forms.MultipleChoiceField(
        label=_('Status'),
        choices=InventoryItemStatusChoices,
        required=False
    )
    tag = TagFilterField(model)


class InventoryItemTemplateFilterForm(DeviceComponentTemplateFilterForm):
    model = InventoryItemTemplate
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('name', 'label', 'role_id', 'manufacturer_id', name=_('Attributes')),
        FieldSet('device_type_id', name=_('Device')),
    )
    role_id = DynamicModelMultipleChoiceField(
        queryset=InventoryItemRole.objects.all(),
        required=False,
        label=_('Role')
    )
    manufacturer_id = DynamicModelMultipleChoiceField(
        queryset=Manufacturer.objects.all(),
        required=False,
        label=_('Manufacturer')
    )


#
# Device component roles
#

class InventoryItemRoleFilterForm(OrganizationalModelFilterSetForm):
    model = InventoryItemRole
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    tag = TagFilterField(model)


#
# Addressing
#

class MACAddressFilterForm(PrimaryModelFilterSetForm):
    model = MACAddress
    fieldsets = (
        FieldSet('q', 'filter_id', 'tag'),
        FieldSet('mac_address', name=_('Attributes')),
        FieldSet('device_id', 'virtual_machine_id', 'assigned', 'primary', name=_('Assignments')),
        FieldSet('owner_group_id', 'owner_id', name=_('Ownership')),
    )
    selector_fields = ('filter_id', 'q', 'device_id', 'virtual_machine_id')
    mac_address = forms.CharField(
        required=False,
        label=_('MAC address'),
    )
    device_id = DynamicModelMultipleChoiceField(
        queryset=Device.objects.all(),
        required=False,
        label=_('Assigned Device'),
    )
    virtual_machine_id = DynamicModelMultipleChoiceField(
        queryset=VirtualMachine.objects.all(),
        required=False,
        label=_('Assigned VM'),
    )
    assigned = forms.NullBooleanField(
        required=False,
        label=_('Assigned to an interface'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        ),
    )
    primary = forms.NullBooleanField(
        required=False,
        label=_('Primary MAC of an interface'),
        widget=forms.Select(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        ),
    )
    tag = TagFilterField(model)


#
# Connections
#

class ConsoleConnectionFilterForm(FilterForm):
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id'
        },
        label=_('Site')
    )
    device_id = DynamicModelMultipleChoiceField(
        queryset=Device.objects.all(),
        required=False,
        query_params={
            'site_id': '$site_id'
        },
        label=_('Device')
    )


class PowerConnectionFilterForm(FilterForm):
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id'
        },
        label=_('Site')
    )
    device_id = DynamicModelMultipleChoiceField(
        queryset=Device.objects.all(),
        required=False,
        query_params={
            'site_id': '$site_id'
        },
        label=_('Device')
    )


class InterfaceConnectionFilterForm(FilterForm):
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Region')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        query_params={
            'region_id': '$region_id'
        },
        label=_('Site')
    )
    device_id = DynamicModelMultipleChoiceField(
        queryset=Device.objects.all(),
        required=False,
        query_params={
            'site_id': '$site_id'
        },
        label=_('Device')
    )
