"""Signals for the resources application.

Based off https://simonwillison.net/2017/Oct/5/django-postgresql-faceted-search/
"""


from django.dispatch import receiver
from django.db.models.signals import (
    post_save,
    # m2m_changed,
)
from django.db.models import Value
from django.contrib.postgres.search import SearchVector
from django.db import transaction
from resources.models import (
    Resource,
)


SEARCH_INDEX_UPDATE_MODELS = (
    Resource,
)


@receiver(post_save)
def on_save(sender, **kwargs):
    """Trigger functions after model save."""
    if issubclass(sender, SEARCH_INDEX_UPDATE_MODELS):
        transaction.on_commit(make_updater(kwargs['instance']))


# TODO: Update on M2M relationships
# @receiver(m2m_changed)
# def on_m2m_changed(sender, **kwargs):
#     instance = kwargs['instance']
#     model = kwargs['model']
#     if model is Tag:
#         transaction.on_commit(make_updater(instance))
#     elif isinstance(instance, Tag):
#         for obj in model.objects.filter(pk__in=kwargs['pk_set']):
#             transaction.on_commit(make_updater(obj))


def make_updater(instance):
    """Return function for updating search index of resource."""
    components = instance.index_contents()
    pk = instance.pk

    def on_commit():
        search_vector_list = []
        for weight, text in components.items():
            search_vector_list.append(
                SearchVector(Value(text), weight=weight)
            )
        search_vectors = search_vector_list[0]
        for search_vector in search_vector_list[1:]:
            search_vectors += search_vector

        instance.__class__.objects.filter(pk=pk).update(
            search_vector=search_vectors
        )

    return on_commit

@@ -221,10 +221,8 @@
 %0A   
- #
  m2m
@@ -231,16 +231,16 @@
 hanged,%0A
+
 )%0Afrom d
@@ -539,16 +539,20 @@
 s after 
+any 
 model sa
@@ -683,29 +683,157 @@
 )%0A%0A%0A
-# TODO: Update on 
+@receiver(m2m_changed)%0Adef on_m2m_changed(sender, **kwargs):%0A    %22%22%22Update search indexes on m2m relationship changes.%0A%0A    When a many to many (
 M2M
+)
  rel
@@ -845,77 +845,326 @@
 ship
-s%0A# @receiver(m2m_changed)%0A# def on_m2m_changed(sender, **kwargs):%0A# 
+ is changed, the%0A    search index should be updated for models that require is.%0A    This only applies to the text search, filter searches are always%0A    up to date.%0A%0A    If an object changes, any items pointing to that object also%0A    updates their index as the text may have changed it uses%0A    for indexing.%0A    %22%22%22%0A
     
@@ -1193,18 +1193,16 @@
 tance'%5D%0A
-# 
     mode
@@ -1225,33 +1225,62 @@
 l'%5D%0A
-# 
     if 
-model is Tag:%0A# 
+issubclass(model, SEARCH_INDEX_UPDATE_MODELS):%0A
     
@@ -1329,18 +1329,16 @@
 tance))%0A
-# 
     elif
@@ -1363,16 +1363,37 @@
 ce, 
-Tag
+SEARCH_INDEX_UPDATE_MODELS
 ):%0A
-# 
     
@@ -1458,10 +1458,8 @@
 %5D):%0A
-# 
     

Update search indexes on M2M changes