# Copyright 2016 Nick Boultbee
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

import random

from quodlibet import _
from quodlibet.order import Order, OrderRemembered


class Reorder(Order):
    """Base class for all `Order`s that potentially reorder the playlist,
    and thus usually identify as a "shuffle" implementation."""


class OrderShuffle(Reorder, OrderRemembered):
    name = "random"
    display_name = _("Random")
    accelerated_name = _("_Random")

    def next(self, playlist, iter):
        super().next(playlist, iter)
        remaining = self.remaining(playlist)

        if not remaining:
            self.reset(playlist)
            return None

        index = random.choice(list(remaining))
        return playlist.get_iter((index,))


class OrderWeighted(Reorder, OrderRemembered):
    name = "weighted"
    display_name = _("Prefer higher rated")
    accelerated_name = _("Prefer _higher rated")

    def next(self, playlist, iter):
        super().next(playlist, iter)
        remaining = self.remaining(playlist)

        # Don't try to search through an empty / played playlist.
        if not remaining:
            self.reset(playlist)
            return None

        total_score = sum([song("~#rating") for song in remaining.values()])
        if total_score == 0:
            # When all songs are rated zero, fall back to unweighted shuffle
            return playlist.get_iter((random.choice(list(remaining)),))
        choice = random.random() * total_score
        current = 0.0
        for i, song in remaining.items():
            current += song("~#rating")
            if current >= choice:
                return playlist.get_iter([i])
        raise ValueError
