"""Middleware to defer slow denormalization  at the end of a request."""
from django.core.cache import cache
from mahjong_ranking import models
from . import LOGGER


class DenormalizationUpdateMiddleware(object):  # Ignore PyLintBear (R0903)
    """To recalculate everything in the queues at the end of a POST request."""

    def process_response(self, request, response):  # Ignore PyLintBear (R0201)
        """Check and process the recalculation queues on each POST request.

        :param request: the django HttpRequest object
        :param response: the django HttpResponse object
        :return: the django HttpResponse object
        """
        event_queue = set()
        season_queue = set()

        if request.method != 'POST':
            return response

        event_ranking_queue = cache.get('event_ranking_queue', set())
        while event_ranking_queue:
            event_id, user_id = event_ranking_queue.pop()
            event_ranking = models.EventRanking.objects.get_or_create(
                event_id=event_id, user_id=user_id)[0]
            event_ranking.recalculate()
            event_queue.add(event_id)
            cache.set('event_ranking_queue', set(), 360)

        kyu_dan_ranking_queue = cache.get('kyu_dan_ranking_queue', set())
        while kyu_dan_ranking_queue:
            user_id, hanchan_start = kyu_dan_ranking_queue.pop()
            kyu_dan_ranking = models.KyuDanRanking.objects.get_or_create(
                user_id=user_id)[0]
            kyu_dan_ranking.calculate(since=hanchan_start)
        cache.set('kyu_dan_ranking_queue', set(), 360)

        ladder_ranking_queue = cache.get('ladder_ranking_queue', set())
        while ladder_ranking_queue:
            season, user_id = ladder_ranking_queue.pop()
            ladder_ranking = models.SeasonRanking.objects.get_or_create(
                user_id=user_id, season=season)[0]
            ladder_ranking.recalculate()
            season_queue.add(season)
        cache.set('ladder_ranking_queue', ladder_ranking_queue, 360)

        for event_id in event_queue:
            eventranking_set = models.EventRanking.objects.filter(
                event_id=event_id).order_by('avg_placement', '-avg_score')
            placement = 1
            for ranking in eventranking_set:
                ranking.placement = placement
                placement += 1
                ranking.save(force_update=True)

        for season in season_queue:
            LOGGER.info(u'Recalculate placements for Season %d', season)
            models.SeasonRanking.objects.update(season=season)
        return response
