import time

from core.chat_blob import ChatBlob
from core.command_alias_service import CommandAliasService
from core.command_param_types import Any, Const, Character, Options
from core.decorators import instance, command, event, timerevent
from core.igncore import IgnCore
from core.text import Text
from modules.standard.raid.leader_controller import LeaderController


@instance()
class AssistController:
    def __init__(self):
        self.assist = []
        self.last_mod = 0

    def inject(self, registry):
        self.leader_controller: LeaderController = registry.get_instance("leader_controller")
        self.command_alias_service: CommandAliasService = registry.get_instance("command_alias_service")
        self.bot: IgnCore = registry.get_instance("bot")
        self.text: Text = registry.get_instance("text")

    def start(self):
        self.command_alias_service.add_alias("callers", "caller")
        self.command_alias_service.add_alias("assist", "caller")

    @command(command="caller", params=[], access_level="member",
             description="Show current assist targets")
    def assist_command(self, _):
        blob = ""
        for caller in self.assist:
            blob += caller.capitalize()
            blob += f" - [{self.text.make_chatcmd('assist', f'/assist {caller}')}]"
            blob += f" [{self.text.make_tellcmd('REM', f'assist del {caller}')}]<br>"
        blob += self.get_assist_output()
        self.last_mod = time.time()
        return ChatBlob(f"Callers ({len(self.assist)})", blob)

    @command(command="caller", params=[Const("clear")], access_level="leader",
             description="Clear all assist targets", sub_command="modify")
    def assist_clear_command(self, request, _):
        if not self.leader_controller.can_use_command(request.sender.char_id):
            return LeaderController.NOT_LEADER_MSG
        if not self.assist:
            return "No assist targets set."
        self.assist = []
        return "Assist targets have been cleared."

    @command(command="caller", params=[Options(["rem", "del"]), Character("char")], access_level="leader",
             description="Remove an assisting target", sub_command="modify")
    def assist_remove_command(self, request, _, char):
        if not self.leader_controller.can_use_command(request.sender.char_id):
            return LeaderController.NOT_LEADER_MSG
        if not self.assist:
            return "No assist targets set."
        self.last_mod = time.time()
        try:
            self.assist.remove(char.name.lower())
            return f"<highlight>{char.name}</highlight> is no longer a caller. " \
                   f"Use: <highlight>{self.get_assist_output()}</highlight>"
        except ValueError:
            return f"<highlight>{char.name}</highlight> is not on the caller list."

    @command(command="caller", params=[Any("assist_targets")], access_level="leader",
             description="Set one or more assist targets",
             sub_command="modify",
             extended_description="Multiple assist targets should be space-delimited")
    def assist_set_command(self, request, assist_targets):
        targets = assist_targets.split(" ")

        if not self.leader_controller.can_use_command(request.sender.char_id):
            return LeaderController.NOT_LEADER_MSG
        for caller in targets:
            if caller.lower() not in self.assist:
                self.assist.append(caller.lower())
        return self.assist_command(request)

    def get_assist_output(self):
        if not self.assist:
            return "No assist targets set."

        return "/macro assist " + "\\n ".join(map(lambda x: "/assist " + x.capitalize(), reversed(self.assist)))

    @event("RAID_END", "automatic caller clearing on raid end")
    def leader_remove_on_leave_private(self, _, event_data):
        if self.assist:
            self.assist = []

    @timerevent("15m", "Purge callers if there's no raid interaction within 60 minutes")
    def callers_purge(self, event_type, event_data):
        if not self.assist:
            return
        if self.last_mod < (time.time()-3600):
            self.assist = []
            self.bot.send_private_channel_message("Callers have been cleared, "
                                                  "as there was no interaction with them for more than 60 minutes.")

