"""Admin integration for django-watson."""

from __future__ import unicode_literals

from django.contrib import admin
from django.contrib.admin.views.main import ChangeList

from watson.registration import SearchEngine, SearchAdapter


admin_search_engine = SearchEngine("admin")


class WatsonSearchChangeList(ChangeList):

    """A change list that takes advantage of django-watson full text search."""

    def get_queryset(self, *args, **kwargs):
        """Creates the query set."""
        # Do the basic searching.
        search_fields = self.search_fields
        self.search_fields = ()
        try:
            qs = super(WatsonSearchChangeList, self).get_queryset(*args, **kwargs)
        finally:
            self.search_fields = search_fields
        # Do the full text searching.
        if self.query.strip():
            qs = self.model_admin.search_engine.filter(qs, self.query, ranking=False)
        return qs


class SearchAdmin(admin.ModelAdmin):

    """
    A ModelAdmin subclass that provides full-text search integration.

    Subclass this admin class and specify a tuple of search_fields for instant
    integration!
    """

    search_engine = admin_search_engine

    search_adapter_cls = SearchAdapter

    @property
    def search_context_manager(self):
        """The search context manager used by this SearchAdmin."""
        return self.search_engine._search_context_manager

    def __init__(self, *args, **kwargs):
        """Initializes the search admin."""
        super(SearchAdmin, self).__init__(*args, **kwargs)
        # Check that the search fields are valid.
        for search_field in self.search_fields or ():
            if search_field[0] in ("^", "@", "="):
                raise ValueError("SearchAdmin does not support search fields prefixed with '^', '=' or '@'")
        # Register with the search engine.
        self.register_model_with_watson()
        # Set up revision contexts on key methods, just in case.
        self.add_view = self.search_context_manager.update_index()(self.add_view)
        self.change_view = self.search_context_manager.update_index()(self.change_view)
        self.delete_view = self.search_context_manager.update_index()(self.delete_view)
        self.changelist_view = self.search_context_manager.update_index()(self.changelist_view)

    def register_model_with_watson(self):
        """Registers this admin class' model with django-watson."""
        if not self.search_engine.is_registered(self.model) and self.search_fields:
            self.search_engine.register(
                self.model,
                fields = self.search_fields,
                adapter_cls = self.search_adapter_cls,
                get_live_queryset = lambda self_: None,  # Ensure complete queryset is used in admin.
            )

    def get_changelist(self, request, **kwargs):
        """Returns the ChangeList class for use on the changelist page."""
        return WatsonSearchChangeList
