from core.aochat.BaseModule import BaseModule
from core.chat_blob import ChatBlob
from core.command_alias_service import CommandAliasService
from core.command_param_types import Options, Int, Any, Const, NamedParameters
from core.db import DB
from core.decorators import instance, command
from core.dict_object import DictObject
from core.event_service import EventService
from core.lookup.pork_service import PorkService
from core.public_channel_service import PublicChannelService
from core.text import Text
from core.igncore import IgnCore
from core.util import Util
from modules.raidbot.tower.tower_service import TowerService
from modules.standard.helpbot.playfield_controller import PlayfieldController


@instance()
class TowerHotController(BaseModule):
    PAGE_SIZE = 9

    # noinspection DuplicatedCode

    def inject(self, registry):
        self.bot: IgnCore = registry.get_instance("bot")
        self.db: DB = registry.get_instance("db")
        self.util: Util = registry.get_instance("util")
        self.text: Text = registry.get_instance("text")
        self.event_service: EventService = registry.get_instance("event_service")
        self.pork_service: PorkService = registry.get_instance("pork_service")
        self.playfield_controller: PlayfieldController = registry.get_instance("playfield_controller")
        self.public_channel_service: PublicChannelService = registry.get_instance("public_channel_service")
        self.towercache: TowerService = registry.get_instance("tower_service")
        self.command_alias_service: CommandAliasService = registry.get_instance("command_alias_service")

    def pre_start(self):
        self.command_alias_service.add_alias('towers', "lc")
        self.command_alias_service.add_alias('tower', "lc")

    @command(command="hot",
             params=[Options(['tl1', 'tl2', 'tl3', 'tl4', 'tl5', 'tl6', 'tl7']), Any('faction', is_optional=True),
                     NamedParameters(["page"])],
             access_level="member",
             description="Shows hot playfields")
    def hot_tl(self, _, tl, faction: str, named_params):
        if faction:
            if faction.startswith("--page="):
                named_params = DictObject({'page': faction[7:]})
                faction = None
        if faction is not None and faction.lower() not in ['omni', 'clan', 'neut', 'neutral']:
            return f"Unknown faction: {faction}"
        tl = tl[2:]
        page = int(named_params.page or "1")
        offset = (page - 1) * self.PAGE_SIZE
        towers = self.towercache.get_towers_hot_tl(int(tl), faction)
        return self.text.format_pagination(towers, offset, page, self.formatter, f"Hot Sites TL{tl} ({len(towers)})",
                                           f"There are no hot sites for TL <highlight>{tl}</highlight>.",
                                           f'hot tl{tl} {faction or ""}', 9)

    def formatter(self, row, _, data):
        return self.towercache.format_entry(row, len(data))

    @command(command="hot",
             params=[Int('level', is_optional=True), Any('faction', is_optional=True), NamedParameters(["page"])],
             access_level="member",
             description="Shows hot playfields by level")
    def hot_level(self, _, level, faction, named_params):
        if faction:
            if faction.startswith("--page="):
                named_params = DictObject({'page': faction[7:]})
                faction = None
        if faction is not None and faction.lower() not in ['omni', 'clan', 'neut', 'neutral']:
            return f"Unknown faction: {faction}"
        if level:
            if level < 0 | level > 220:
                return f"Level out of range: {level}"
        page = int(named_params.page or "1")
        offset = (page - 1) * self.PAGE_SIZE
        towers = self.towercache.get_towers_hot_level(level, faction)
        level = f"{level}" if level else ""
        faction = f"{faction} " if faction else ""
        return self.text.format_pagination(towers, offset, page, self.formatter, f"Hot Towersites ({len(towers)})",
                                           f"There are no hot sites.", f'hot {level}{faction}', 9)

    @command(command="free", params=[],
             access_level="member",
             description="Shows hot playfields by level")
    def free(self, _, ):
        blob = ""
        towers = self.towercache.get_free()
        for row in towers:
            blob += self.towercache.format_entry(row, len(towers))

        return ChatBlob(f"FREE Towersites ({len(towers)})", blob) if blob else f"No free towersites found."

    @command(command="lc", params=[], access_level="member",
             description="See a list of land control tower sites in a particular playfield")
    def lc(self, _):
        hot, cold, unplanted = 0, 0, 0
        clan, omni, neut = 0, 0, 0
        last_pf = 0
        previous = {}
        blob = ""

        def number(numb):
            if numb < 10:
                return f"<black>0</black>{numb}"
            return numb

        for tower in self.towercache.get_towers_all():
            if tower.id != last_pf:
                if last_pf == 0:
                    previous = tower
                    last_pf = tower.id
                    continue
                blob += f"<red>{number(hot)}</red> <cyan>{number(cold)}</cyan> <grey>{number(unplanted)}</grey> :: " \
                        f"<clan>{number(clan)}</clan> <neutral>{number(neut)}</neutral> <omni>{number(omni)}</omni> " \
                        f"[{self.text.make_tellcmd(previous.short_name, f'lc {previous.long_name}')}] " \
                        f"{previous.long_name}\n"
                hot, cold, unplanted = 0, 0, 0
                clan, omni, neut = 0, 0, 0

                previous = tower
                last_pf = tower.id

            site = self.towercache.is_hot(tower)
            if site == 0:
                cold += 1
            elif site == -1:
                unplanted += 1
            elif site == 1:
                hot += 1
            faction = tower.get('faction', None)
            if faction:
                faction = faction.lower
                if faction == "omni":
                    omni += 1
                elif faction == "clan":
                    clan += 1
                else:
                    neut += 1

        return ChatBlob('All Tower Sites', blob)

    @command(command="lc", params=[Const("org"), Any("org_name", is_optional=True)], access_level="member",
             description="See a list of land control tower sites in a particular playfield")
    def lc_org(self, _, _1, org):
        towers = []
        try:
            org = int(org)
        except ValueError:
            pass
        if type(org) == str:
            orgs = self.db.query(
                "SELECT * from all_orgs where org_name LIKE ? and org_id in "
                "(SELECT org_id from towers group by org_id)",
                [f"%{org.replace(' ', '%')}%"])
            if len(orgs) == 1:
                towers = self.towercache.get_towers_by_org(orgs[0].org_id)

            elif len(orgs) == 0:
                return "Your search returned no orgs."
            else:
                blob = "Your search had multiple results; please pick an org:<br>"
                for org in orgs:
                    blob += "[%s] <highlight>%s<end> (<highlight>%s<end>) <%s>%s<end> [<highlight>%s<end> " \
                            "members]<br><pagebreak>" \
                            % (self.text.make_chatcmd("Towers", "/tell <myname> lc org %s" % org.org_id),
                               org.org_name, org.org_id, org.faction.lower(), org.faction, org.member_count)
                return ChatBlob("Pick an Org", blob)
        elif type(org) == int:
            if len(self.db.query("SELECT org_id from all_orgs where org_id=?", [int(org)])) == 0:
                return "Your search returned no orgs."
            else:
                towers = self.towercache.get_towers_by_org(org)

        title = f"Towersites of the org {org}"

        blob = ""
        for tower in towers:
            blob += self.towercache.format_entry(tower, len(towers))

        return ChatBlob(title, blob)

    @command(command="lc", params=[Any("playfield"), Int("site_number", is_optional=True)], access_level="member",
             description="See a list of land control tower sites in a particular playfield")
    def lc_playfield(self, _, playfield_name, site_number):
        playfield = self.playfield_controller.get_playfield_by_name(playfield_name)
        if not playfield:
            return "Could not find playfield <highlight>%s</highlight>." % playfield_name
        if site_number:
            title = f"Tower site x{site_number} in {playfield.long_name}"
            towers = self.towercache.get_towers_by_pf_site(playfield.id, site_number)
        else:
            title = f"Tower sites in {playfield.long_name}"
            towers = self.towercache.get_towers_by_pf(playfield.id)

        blob = ""
        for tower in towers:
            blob += self.towercache.format_entry(tower, len(towers))
            if site_number:
                blob += "More to come... stay tuned."

        return ChatBlob(title, blob)
