content: import zoneinfo
  from dataclasses import dataclass
  from typing import Optional
  from urllib.parse import quote
  
  import django_tables2 as tables
  from django.conf import settings
  from django.contrib.auth.context_processors import auth
  from django.contrib.auth.models import AnonymousUser
  from django.db.models import DateField, DateTimeField
  from django.template import Context, Template
  from django.urls import reverse
  from django.utils.dateparse import parse_date
  from django.utils.html import escape
  from django.utils.safestring import mark_safe
  from django.utils.translation import gettext_lazy as _
  from django_tables2.columns import library
  from django_tables2.utils import Accessor
  
  from extras.choices import CustomFieldTypeChoices
  from utilities.object_types import object_type_identifier, object_type_name
  from utilities.permissions import get_permission_for_model
  from utilities.templatetags.builtins.filters import render_markdown
  from utilities.views import get_action_url
  
  __all__ = (
      'ActionsColumn',
      'ArrayColumn',
      'BooleanColumn',
      'ChoiceFieldColumn',
      'ChoicesColumn',
      'ColorColumn',
      'ColoredLabelColumn',
      'ContentTypeColumn',
      'ContentTypesColumn',
      'CustomFieldColumn',
      'CustomLinkColumn',
      'DictColumn',
      'DistanceColumn',
      'DurationColumn',
      'LinkedCountColumn',
      'MarkdownColumn',
      'ManyToManyColumn',
      'MPTTColumn',
      'TagColumn',
      'TemplateColumn',
      'ToggleColumn',
      'UtilizationColumn',
  )
  
  
  #
  # Django-tables2 overrides
  #
  
  @library.register
  class DateColumn(tables.Column):
      """
      Render a datetime.date in ISO 8601 format.
      """
      def render(self, value):
          if value:
              return value.isoformat()
  
      def value(self, value):
          if value:
              return value.isoformat()
  
      @classmethod
      def from_field(cls, field, **kwargs):
          if isinstance(field, DateField):
              return cls(**kwargs)
  
  
  @library.register
  class DateTimeColumn(tables.Column):
      """
      Render a datetime.datetime in ISO 8601 format.
  
      Args:
          timespec: Granularity specification; passed through to datetime.isoformat()
      """
      def __init__(self, *args, timespec='seconds', **kwargs):
          self.timespec = timespec
          super().__init__(*args, **kwargs)
  
      def render(self, value):
          if value:
              current_tz = zoneinfo.ZoneInfo(settings.TIME_ZONE)
              value = value.astimezone(current_tz)
              return f"{value.date().isoformat()} {value.time().isoformat(timespec=self.timespec)}"
  
      def value(self, value):
          if value:
              return value.isoformat()
  
      @classmethod
      def from_field(cls, field, **kwargs):
          if isinstance(field, DateTimeField):
              return cls(**kwargs)
  
  
  class DurationColumn(tables.Column):
      """
      Express a duration of time (in minutes) in a human-friendly format. Example: 437 minutes becomes "7h 17m"
      """
      def render(self, value):
          ret = ''
          if days := value // 1440:
              ret += f'{days}d '
          if hours := value % 1440 // 60:
              ret += f'{hours}h '
          if minutes := value % 60:
              ret += f'{minutes}m'
          return ret.strip()
  
      def value(self, value):
          return value
  
  
  class ManyToManyColumn(tables.ManyToManyColumn):
      """
      Overrides django-tables2's stock ManyToManyColumn to ensure that value() returns only plaintext data.
      """
      def value(self, value):
          items = [self.transform(item) for item in self.filter(value)]
          return self.separator.join(items)
  
  
  class TemplateColumn(tables.TemplateColumn):
      """
      Overrides django-tables2's stock TemplateColumn class to render a placeholder symbol if the returned value
      is an empty string.
      """
      PLACEHOLDER = mark_safe('&mdash;')
  
      def __init__(self, export_raw=False, **kwargs):
          """
          Args:
              export_raw: If true, data export returns the raw field value rather than the rendered template. (Default:
                          False)
          """
          super().__init__(**kwargs)
          self.export_raw = export_raw
  
      def render(self, *args, **kwargs):
          ret = super().render(*args, **kwargs)
          if not ret.strip():
              return self.PLACEHOLDER
          return ret
  
      def value(self, **kwargs):
          if self.export_raw:
              # Skip template rendering and export raw value
              return kwargs.get('value')
  
          ret = super().value(**kwargs)
          if ret == self.PLACEHOLDER:
              return ''
          return ret
  
  
  #
  # Custom columns
  #
  
  class ToggleColumn(tables.CheckBoxColumn):
      """
      Extend CheckBoxColumn to add a "toggle all" checkbox in the column header.
      """
      def __init__(self, *args, **kwargs):
          default = kwargs.pop('default', '')
          visible = kwargs.pop('visible', False)
          if 'attrs' not in kwargs:
              kwargs['attrs'] = {
                  'th': {
                      'class': 'w-1',
                      'aria-label': _('Select all'),
                  },
                  'td': {
                      'class': 'w-1',
                  },
                  'input': {
                      'class': 'form-check-input'
                  }
              }
          super().__init__(*args, default=default, visible=visible, **kwargs)
  
      @property
      def header(self):
          title_text = _('Toggle all')
          return mark_safe(f'<input type="checkbox" class="toggle form-check-input" title="{title_text}" />')
  
  
  class BooleanColumn(tables.Column):
      """
      Custom implementation of BooleanColumn to render a nicely-formatted checkmark or X icon instead of a Unicode
      character.
      """
      TRUE_MARK = mark_safe('<span class="text-success"><i class="mdi mdi-check-bold"></i></span>')
      FALSE_MARK = mark_safe('<span class="text-danger"><i class="mdi mdi-close-thick"></i></span>')
      EMPTY_MARK = mark_safe('<span class="text-muted">&mdash;</span>')  # Placeholder
  
      def __init__(self, *args, true_mark=TRUE_MARK, false_mark=FALSE_MARK, **kwargs):
          self.true_mark = true_mark
          self.false_mark = false_mark
          super().__init__(*args, **kwargs)
  
      def render(self, value):
          if value is None:
              return self.EMPTY_MARK
          if value and self.true_mark:
              return self.true_mark
          if not value and self.false_mark:
              return self.false_mark
          return self.EMPTY_MARK
  
      def value(self, value):
          return str(value)
  
  
  @dataclass
  class ActionsItem:
      title: str
      icon: str
      permission: Optional[str] = None
      css_class: Optional[str] = 'secondary'
  
  
  class ActionsColumn(tables.Column):
      """
      A dropdown menu which provides edit, delete, and changelog links for an object. Can optionally include
      additional buttons rendered from a template string.
  
      :param actions: The ordered list of dropdown menu items to include
      :param extra_buttons: A Django template string which renders additional buttons preceding the actions dropdown
      :param split_actions: When True, converts the actions dropdown menu into a split button with first action as the
          direct button link and icon (default: True)
      """
      attrs = {
          'td': {
              'class': 'text-end text-nowrap noprint p-1'
          }
      }
      empty_values = ()
      actions = {
          'edit': ActionsItem('Edit', 'pencil', 'change', 'warning'),
          'delete': ActionsItem('Delete', 'trash-can-outline', 'delete', 'danger'),
          'changelog': ActionsItem('Changelog', 'history'),
      }
  
      def __init__(self, *args, actions=('edit', 'delete', 'changelog'), extra_buttons='', split_actions=True, **kwargs):
          super().__init__(*args, **kwargs)
  
          self.extra_buttons = extra_buttons
          self.split_actions = split_actions
  
          # Determine which actions to enable
          self.actions = {
              name: self.actions[name] for name in actions
          }
  
      def header(self):
          return ''
  
      def render(self, record, table, **kwargs):
          model = table.Meta.model
  
          # Skip if no actions or extra buttons are defined
          if not (self.actions or self.extra_buttons):
              return ''
          # Skip dummy records (e.g. available VLANs or IP ranges replacing individual IPs)
          if type(record) is not model or not getattr(record, 'pk', None):
              return ''
  
          if request := getattr(table, 'context', {}).get('request'):
              return_url = request.GET.get('return_url', request.get_full_path())
              url_appendix = f'?return_url={quote(return_url)}'
          else:
              url_appendix = ''
  
          html = ''
  
          # Compile actions menu
          button = None
          dropdown_class = 'secondary'
          dropdown_links = []
          user = getattr(request, 'user', AnonymousUser())
          for idx, (action, attrs) in enumerate(self.actions.items()):
              permission = get_permission_for_model(model, attrs.permission)
              if attrs.permission is None or user.has_perm(permission):
                  url = get_action_url(model, action=action, kwargs={'pk': record.pk})
  
                  # Render a separate button if a) only one action exists, or b) if split_actions is True
                  if len(self.actions) == 1 or (self.split_actions and idx == 0):
                      dropdown_class = attrs.css_class
                      button = (
                          f'<a class="btn btn-sm btn-{attrs.css_class}" href="{url}{url_appendix}" type="button" '
                          f'aria-label="{attrs.title}">'
                          f'<i class="mdi mdi-{attrs.icon}"></i></a>'
                      )
  
                  # Add dropdown menu items
                  else:
                      dropdown_links.append(
                          f'<li><a class="dropdown-item" href="{url}{url_appendix}">'
                          f'<i class="mdi mdi-{attrs.icon}"></i> {attrs.title}</a></li>'
                      )
  
          # Create the actions dropdown menu
          toggle_text = _('Toggle Dropdown')
          if button and dropdown_links:
              html += (
                  f'<span class="btn-group dropdown">'
                  f'  {button}'
                  f'  <a class="btn btn-sm btn-{dropdown_class} dropdown-toggle" type="button" data-bs-toggle="dropdown" '
                  f'style="padding-left: 2px">'
                  f'  <span class="visually-hidden">{toggle_text}</span></a>'
                  f'  <ul class="dropdown-menu">{"".join(dropdown_links)}</ul>'
                  f'</span>'
              )
          elif button:
              html += button
          elif dropdown_links:
              html += (
                  f'<span class="btn-group dropdown">'
                  f'  <a class="btn btn-sm btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">'
                  f'  <span class="visually-hidden">{toggle_text}</span></a>'
                  f'  <ul class="dropdown-menu">{"".join(dropdown_links)}</ul>'
                  f'</span>'
              )
  
          # Render any extra buttons from template code
          if self.extra_buttons:
              template = Template(self.extra_buttons)
              context = getattr(table, "context", Context())
              context.update({'record': record})
              html = template.render(context) + html
  
          return mark_safe(html)
  
  
  class ChoiceFieldColumn(tables.Column):
      """
      Render a model's static ChoiceField with its value from `get_FOO_display()` as a colored badge. Background color is
      set by the instance's get_FOO_color() method, if defined, or can be overridden by a "color" callable.
      """
      DEFAULT_BG_COLOR = 'secondary'
  
      def __init__(self, *args, color=None, **kwargs):
          super().__init__(*args, **kwargs)
          self.color = color
  
      def render(self, record, bound_column, value):
          if value in self.empty_values:
              return self.default
  
          # Determine the background color to use (use "color" callable if given, else try calling object.get_FOO_color())
          if self.color:
              bg_color = self.color(record)
          else:
              try:
                  bg_color = getattr(record, f'get_{bound_column.name}_color')() or self.DEFAULT_BG_COLOR
              except AttributeError:
                  bg_color = self.DEFAULT_BG_COLOR
  
          return mark_safe(f'<span class="badge text-bg-{bg_color}">{value}</span>')
  
      def value(self, value):
          return value
  
  
  class ContentTypeColumn(tables.Column):
      """
      Display a ContentType instance.
      """
      def render(self, value):
          if value is None:
              return None
          return object_type_name(value, include_app=False)
  
      def value(self, value):
          if value is None:
              return None
          return object_type_identifier(value)
  
  
  class ContentTypesColumn(tables.ManyToManyColumn):
      """
      Display a list of ContentType instances.
      """
      def __init__(self, separator=None, *args, **kwargs):
          # Use a line break as the default separator
          if separator is None:
              separator = mark_safe('<br />')
          super().__init__(separator=separator, *args, **kwargs)
  
      def transform(self, obj):
          return object_type_name(obj, include_app=False)
  
      def value(self, value):
          return ','.join([
              object_type_identifier(ot) for ot in self.filter(value)
          ])
  
  
  class ColorColumn(tables.Column):
      """
      Display an arbitrary color value, specified in RRGGBB format.
      """
      def render(self, value):
          return mark_safe(
              f'<span class="color-label" style="background-color: #{value}">&nbsp;</span>'
          )
  
      def value(self, value):
          return f'#{value}'
  
  
  class ColoredLabelColumn(tables.TemplateColumn):
      """
      Render a related object as a colored label. The related object must have a `color` attribute (specifying
      an RRGGBB value) and a `get_absolute_url()` method.
      """
      template_code = """
  {% load helpers %}
    {% if value %}
    <span class="badge" style="color: {{ value.color|fgcolor }}; background-color: #{{ value.color }}">
      <a href="{{ value.get_absolute_url }}">{{ value }}</a>
    </span>
  {% else %}
    &mdash;
  {% endif %}
  """
  
      def __init__(self, *args, **kwargs):
          super().__init__(template_code=self.template_code, *args, **kwargs)
  
      def value(self, value):
          return str(value)
  
  
  class LinkedCountColumn(tables.Column):
      """
      Render a count of related objects linked to a filtered URL.
  
      :param viewname: The view name to use for URL resolution
      :param view_kwargs: Additional kwargs to pass for URL resolution (optional)
      :param url_params: A dict of query parameters to append to the URL (e.g. ?foo=bar) (optional)
      """
      def __init__(self, viewname, *args, view_kwargs=None, url_params=None, default=0, **kwargs):
          self.viewname = viewname
          self.view_kwargs = view_kwargs or {}
          self.url_params = url_params
          super().__init__(*args, default=default, **kwargs)
  
      def render(self, record, value):
          if value:
              url = reverse(self.viewname, kwargs=self.view_kwargs)
              if self.url_params:
                  url += '?' + '&'.join([
                      f'{k}={getattr(record, v) or settings.FILTERS_NULL_CHOICE_VALUE}'
                      for k, v in self.url_params.items()
                  ])
              return mark_safe(f'<a href="{url}">{escape(value)}</a>')
          return value
  
      def value(self, value):
          return value
  
  
  class TagColumn(tables.TemplateColumn):
      """
      Display a list of Tags assigned to the object.
      """
      template_code = """
      {% load helpers %}
      {% for tag in value.all %}
          {% tag tag url_name %}
      {% empty %}
          <span class="text-muted">&mdash;</span>
      {% endfor %}
      """
  
      def __init__(self, url_name=None):
          super().__init__(
              orderable=False,
              template_code=self.template_code,
              extra_context={'url_name': url_name},
              verbose_name=_('Tags'),
          )
  
      def value(self, value):
          return ",".join([tag.name for tag in value.all()])
  
  
  class CustomFieldColumn(tables.Column):
      """
      Display custom fields in the appropriate format.
      """
      def __init__(self, customfield, *args, **kwargs):
          self.customfield = customfield
          kwargs['accessor'] = Accessor(f'custom_field_data__{customfield.name}')
          if 'verbose_name' not in kwargs:
              kwargs['verbose_name'] = customfield.label or customfield.name
          # We can't logically sort on FK values
          if customfield.type in (
              CustomFieldTypeChoices.TYPE_OBJECT,
              CustomFieldTypeChoices.TYPE_MULTIOBJECT
          ):
              kwargs['orderable'] = False
  
          super().__init__(*args, **kwargs)
  
      @staticmethod
      def _linkify_item(item):
          if hasattr(item, 'get_absolute_url'):
              return f'<a href="{item.get_absolute_url()}">{escape(item)}</a>'
          return escape(item)
  
      def render(self, value):
          if self.customfield.type == CustomFieldTypeChoices.TYPE_BOOLEAN and value is True:
              return mark_safe('<i class="mdi mdi-check-bold text-success"></i>')
          if self.customfield.type == CustomFieldTypeChoices.TYPE_BOOLEAN and value is False:
              return mark_safe('<i class="mdi mdi-close-thick text-danger"></i>')
          if self.customfield.type == CustomFieldTypeChoices.TYPE_URL:
              return mark_safe(f'<a href="{escape(value)}">{escape(value)}</a>')
          if self.customfield.type == CustomFieldTypeChoices.TYPE_SELECT:
              return self.customfield.get_choice_label(value)
          if self.customfield.type == CustomFieldTypeChoices.TYPE_MULTISELECT:
              return ', '.join(self.customfield.get_choice_label(v) for v in value)
          if self.customfield.type == CustomFieldTypeChoices.TYPE_MULTIOBJECT:
              return mark_safe(', '.join(
                  self._linkify_item(obj) for obj in self.customfield.deserialize(value)
              ))
          if self.customfield.type == CustomFieldTypeChoices.TYPE_LONGTEXT and value:
              return render_markdown(value)
          if self.customfield.type == CustomFieldTypeChoices.TYPE_DATE and value:
              return parse_date(value).isoformat()
          if value is not None:
              obj = self.customfield.deserialize(value)
              return mark_safe(self._linkify_item(obj))
          return self.default
  
      def value(self, value):
          if isinstance(value, list):
              return ','.join(str(v) for v in self.customfield.deserialize(value))
          if value is not None:
              return self.customfield.deserialize(value)
          return self.default
  
  
  class CustomLinkColumn(tables.Column):
      """
      Render a custom link as a table column.
      """
      def __init__(self, customlink, *args, **kwargs):
          self.customlink = customlink
          kwargs.setdefault('accessor', Accessor('pk'))
          kwargs.setdefault('orderable', False)
          kwargs.setdefault('verbose_name', customlink.name)
  
          super().__init__(*args, **kwargs)
  
      def _render_customlink(self, record, table):
          context = {
              'object': record,
              'debug': settings.DEBUG,
          }
          if request := getattr(table, 'context', {}).get('request'):
              # If the request is available, include it as context
              context.update({
                  'request': request,
                  **auth(request),
              })
  
          return self.customlink.render(context)
  
      def render(self, record, table, **kwargs):
          try:
              if rendered := self._render_customlink(record, table):
                  return mark_safe(f'<a href="{rendered["link"]}"{rendered["link_target"]}>{rendered["text"]}</a>')
          except Exception as e:
              error_text = _('Error')
              return mark_safe(f'<span class="text-danger" title="{e}"><i class="mdi mdi-alert"></i> {error_text}</span>')
          return ''
  
      def value(self, record, table, **kwargs):
          try:
              if rendered := self._render_customlink(record, table):
                  return rendered['link']
          except Exception:
              pass
          return None
  
  
  class MPTTColumn(tables.TemplateColumn):
      """
      Display a nested hierarchy for MPTT-enabled models.
      """
      template_code = """
          {% load helpers %}
          {% if not table.order_by %}
            {% for i in record.level|as_range %}<i class="mdi mdi-circle-small"></i>{% endfor %}
          {% endif %}
          <a href="{{ record.get_absolute_url }}">{{ record.name }}</a>
      """
  
      def __init__(self, *args, **kwargs):
          super().__init__(
              template_code=self.template_code,
              attrs={'td': {'class': 'text-nowrap'}},
              *args,
              **kwargs
          )
  
      def value(self, value):
          return value
  
  
  class UtilizationColumn(tables.TemplateColumn):
      """
      Display a colored utilization bar graph.
      """
      template_code = """{% load helpers %}{% if record.pk %}{% utilization_graph value %}{% endif %}"""
  
      def __init__(self, *args, **kwargs):
          super().__init__(template_code=self.template_code, *args, **kwargs)
  
      def value(self, value):
          return f'{value}%'
  
  
  class MarkdownColumn(tables.TemplateColumn):
      """
      Render a Markdown string.
      """
      template_code = """
      {% if value %}
        {{ value|markdown }}
      {% else %}
        &mdash;
      {% endif %}
      """
  
      def __init__(self, **kwargs):
          super().__init__(
              template_code=self.template_code,
              **kwargs,
          )
  
      def value(self, value):
          return value
  
  
  class ArrayColumn(tables.Column):
      """
      List array items as a comma-separated list.
      """
      def __init__(self, *args, max_items=None, func=str, **kwargs):
          self.max_items = max_items
          self.func = func
          super().__init__(*args, **kwargs)
  
      def render(self, value):
          omitted_count = 0
  
          # Limit the returned items to the specified maximum number (if any)
          if self.max_items:
              omitted_count = len(value) - self.max_items
              value = value[:self.max_items - 1]
  
          # Apply custom processing function (if any) per item
          if self.func:
              value = [self.func(v) for v in value]
  
          # Annotate omitted items (if applicable)
          if omitted_count > 0:
              value.append(f'({omitted_count} more)')
  
          return ', '.join(value)
  
  
  class ChoicesColumn(tables.Column):
      """
      Display the human-friendly labels of a set of choices.
      """
      def __init__(self, *args, max_items=None, **kwargs):
          self.max_items = max_items
          super().__init__(*args, **kwargs)
  
      def render(self, value):
          omitted_count = 0
          value = [v[1] for v in value]
  
          # Limit the returned items to the specified maximum number (if any)
          if self.max_items:
              omitted_count = len(value) - self.max_items
              value = value[:self.max_items - 1]
  
          # Annotate omitted items (if applicable)
          if omitted_count > 0:
              value.append(f'({omitted_count} more)')
  
          return ', '.join(value)
  
  
  class DistanceColumn(TemplateColumn):
      """
      Distance with template code for formatting
      """
      template_code = """
      {% load helpers %}
      {% if record.distance %}{{ record.distance|floatformat:"-2" }} {{ record.distance_unit }}{% endif %}
      """
  
      def __init__(self, template_code=template_code, order_by='_abs_distance', **kwargs):
          super().__init__(template_code=template_code, order_by=order_by, **kwargs)
  
  
  class DictColumn(tables.Column):
      """
      Render a dictionary of data in a simple key: value format, one pair per line.
      """
      def render(self, value):
          output = '<br />'.join([
              f'{escape(k)}: {escape(v)}' for k, v in value.items()
          ])
          return mark_safe(output)
  