# written by Nicolas Neubauer
# see LICENSE.txt for license information

import time
import logging


class Reranker:

    def getID(self):
        """the ID that is stored in the clicklog 'reranking_strategy' field for later comparison"""
        return 0

    def rerank(self, hits, keywords, torrent_db, pref_db, mypref_db, search_db):
        """takes hits and reorders them given the current keywords"""
        return hits


class DefaultTorrentReranker(Reranker):

    """ just leave the hits alone """
    def getID(self):
        return 1

    def rerank(self, hits, keywords, torrent_db, pref_db, mypref_db, search_db):
        return hits


class TestReranker(Reranker):

    """ for testing purposes only """
    def getID(self):
        return 2

    def rerank(self, hits, keywords, torrent_db, pref_db, mypref_db, search_db):
        if len(hits) > 1:
            h = hits[0]
            hits[0] = hits[1]
            hits[1] = h
        return hits


class SwapFirstTwoReranker(Reranker):

    """ swaps first and second place if second place has been frequently selected from bad position """

    def __init__(self):
        self._logger = logging.getLogger(self.__class__.__name__)

        self.MAX_SEEN_BEFORE_RERANK = 5
        self.MAX_POPULAR_RATIO = 5

    def getID(self):
        return 2

    def rerank(self, hits, keywords, torrent_db, pref_db, mypref_db, search_db):
        if len(hits) < 2:
            return hits

        torrent_id_0 = hits[0].get('torrent_id', None)
        torrent_id_1 = hits[1].get('torrent_id', None)
        if not torrent_id_0 or not torrent_id_1:
            self._logger.debug("reranking: torrent_id=0 in hits, exiting")
            # we got some problems elsewhere, don't add to it
            return hits

        (num_hits_0, position_score_0) = pref_db.getPositionScore(torrent_id_0, keywords)
        (num_hits_1, position_score_1) = pref_db.getPositionScore(torrent_id_1, keywords)
        self._logger.debug("reranking:  first torrent (%d): (num, score)= (%s, %s)", torrent_id_0, num_hits_0, position_score_0)
        self._logger.debug("reranking: second torrent (%d): (num, score)= (%s, %s)", torrent_id_1, num_hits_1, position_score_1)

        if (num_hits_0 < self.MAX_SEEN_BEFORE_RERANK or num_hits_1 < self.MAX_SEEN_BEFORE_RERANK):
            # only start thinking about reranking if we have seen enough samples
            self._logger.debug("reranking: not enough samples, not reranking")
            return hits

        if (num_hits_0 / num_hits_1 > self.MAX_POPULAR_RATIO):
            # if number one is much more popular, keep everything as it is
            self._logger.debug("reranking: first torrent is too popular, not reranking")
            return hits

        # if all these tests are successful, we may swap first and second if second
        # has gotten hits from worse positions than first

        if position_score_0 < position_score_1:
            self._logger.debug("reranking: second torrent has better position score, reranking!")
            h = hits[0]
            hits[0] = hits[1]
            hits[1] = h
        else:
            self._logger.debug("reranking: second torrent does not have better position score, reranking!")

        return hits

_rerankers = [DefaultTorrentReranker(), SwapFirstTwoReranker()]


def getTorrentReranker():
    global _rerankers
    index = int(time.strftime("%H")) % (len(_rerankers))
    return _rerankers[index]
