# SPDX-FileCopyrightText: 2016-2021 Bruce Cowan <bruce@bcowan.me.uk>
#
# SPDX-License-Identifier: GPL-3.0-or-later

from __future__ import annotations

import collections
import re

import errbot


class Karma(errbot.BotPlugin):
    """Karma service"""

    def activate(self):
        super().activate()

        if "karma" not in self:
            self["karma"] = collections.Counter()

    def _change_karma(self, target: str, value: int) -> str:
        target = target.strip()

        with self.mutable("karma") as k:
            k[target] += value

            if k[target] == 0:
                del k[target]

        return f"Karma for '{target}' is now {self['karma'][target]}"

    @errbot.re_botcmd(pattern=r"(.+)\+\+", prefixed=False, flags=re.IGNORECASE)
    def on_karma_inc(self, message: errbot.Message, match: re.Match) -> str | None:
        """Adds karma"""
        if message.frm == self.bot_identifier:
            return
        if "c++" in message.body.casefold():
            return

        return self._change_karma(match.group(1), 1)

    @errbot.re_botcmd(pattern=r"(.+)--", prefixed=False, flags=re.IGNORECASE)
    def on_karma_dec(self, message: errbot.Message, match: re.Match) -> str | None:
        """Removes karma"""
        if message.frm == self.bot_identifier:
            return

        return self._change_karma(match.group(1), -1)

    @errbot.botcmd
    def karma(self, message: errbot.Message, args: str | None) -> str:
        """Gets karma"""
        if not args:
            return "**Usage**: !karma <target>"

        return f"Karma for '{args}' is {self['karma'][args]}"

    @errbot.botcmd
    def karma_top(self, message: errbot.Message, args: str | None) -> str:
        """Gets the top n items"""
        if len(self["karma"]) == 0:
            return "There are no items with karma"

        try:
            num = int(args)
        except (TypeError, ValueError):
            num = 5

        top = self["karma"].most_common(num)
        return ", ".join([f"{k}: {v}" for k, v in top])

    @errbot.botcmd
    def karma_bottom(self, message: errbot.Message, args: str | None) -> str:
        """Gets the bottom n items"""
        if len(self["karma"]) == 0:
            return "There are no items with karma"

        try:
            num = int(args)
        except (TypeError, ValueError):
            num = 5

        bottom = self["karma"].most_common()[: -num - 1 : -1]
        return ", ".join([f"{k}: {v}" for k, v in bottom])

    @errbot.botcmd
    def karma_reset(self, message: errbot.Message, args: str | None) -> str:
        args = args.strip()

        if args not in self["karma"]:
            return "**Error**: no such item"

        with self.mutable("karma") as k:
            del k[args]
        return f"Deleted {args}"