import time
import typing
from datetime import datetime

from core.buddy_service import BuddyService
from core.chat_blob import ChatBlob
from core.command_alias_service import CommandAliasService
from core.db import DB
from core.decorators import instance, command
from core.job_scheduler import JobScheduler
from core.logger import Logger
from core.text import Text
from core.igncore import IgnCore
from core.util import Util
if typing.TYPE_CHECKING:
    from core.lookup.pork_service import PorkService
    from core.setting_service import SettingService
    from modules.core.accounting.preference_controller import PreferenceController
    from modules.core.accounting.services.account_service import AccountService
    from modules.core.ban.ban_service import BanService
    from modules.core.discord.discord_controller import DiscordController
    from modules.onlinebot.online.org_alias_controller import OrgAliasController


@instance()
class WeeklyController:
    # dates = {"ai": [1618704000, 1619395200],
    #          "bs": [1619913600, 1620604800],
    #          "dio": [1621123200, 1621814400],
    #          }
    dates = {"ai": [1627171200, 1627862400],
             "bs": [1628380800, 1629072000],
             "dio": [1629590400, 1630281600],
             }
    duration = 60 * 60 * 24 * 42  # 3628800

    def inject(self, registry):
        self.logger = Logger(__name__)
        self.bot: IgnCore = registry.get_instance("bot")
        self.db: DB = registry.get_instance("db")
        self.text: Text = registry.get_instance("text")
        self.ban: BanService = registry.get_instance("ban_service")
        self.util: Util = registry.get_instance("util")
        self.account_service: AccountService = registry.get_instance("account_service")
        self.pork: PorkService = registry.get_instance("pork_service")
        self.org_pork: PorkService = registry.get_instance("org_pork_service")
        self.command_alias_service: CommandAliasService = registry.get_instance("command_alias_service")
        self.buddy_service: BuddyService = registry.get_instance("buddy_service")
        self.setting_service: SettingService = registry.get_instance("setting_service")
        self.discord: DiscordController = registry.get_instance("discord_controller")
        self.job_schedule: JobScheduler = registry.get_instance("job_scheduler")
        self.preferences: PreferenceController = registry.get_instance("preference_controller")
        self.alias_controller: OrgAliasController = registry.get_instance("org_alias_controller")
        self.account_service: AccountService = registry.get_instance("account_service")

    @command(command="icc", params=[], description="ICC Weekly", access_level="member")
    def show_raids(self, _):
        events = [self.get_next_bs(),
                  self.get_next_ai(),
                  self.get_next_dio()]

        events = sorted(events, key=lambda event: event.start)
        current = "None"
        if events[0].is_running():
            current = self.get_long_name(events[0].type) + \
                      f' [Ends in {self.util.time_to_readable(events[0].end - time.time())}]'
        blob = "" \
               f"Current Mission: {current}\n" \
               f"\n" \
               f"Planned:\n"
        for i in events:
            blob += self.format_entry(i)
        return ChatBlob("ICC Weekly Missions", blob)

    # noinspection PyShadowingNames
    def time_to_readable(self, time):
        return datetime.utcfromtimestamp(time).strftime("%d.%m.%Y")

    def format_entry(self, event):
        return f"{self.get_long_name(event.type)}: <highlight>{self.time_to_readable(event.start)}</highlight> " \
               f"-> <highlight>{self.time_to_readable(event.end - 1)}</highlight>\n" if not event.is_running() else ""

    def get_long_name(self, event_type):
        return {"ai": "Alien Weekly",
                "bs": "Battlestation Weekly",
                "dio": "Dust it Off Weekly"}.get(event_type)

    def get_next_event(self, event_type, now):
        cycle = (now - self.dates[event_type][0]) / self.duration
        cycle = round(cycle)
        event = WeeklyEvent(event_type, self.dates[event_type][0] + cycle * self.duration,
                            self.dates[event_type][1] + cycle * self.duration)
        if event.end <= now:
            event.start += self.duration
            event.end += self.duration
        return event

    def get_next_dio(self, when=0):
        when = time.time() if when == 0 else when
        return self.get_next_event("dio", when)

    def get_next_bs(self, when=0):
        when = time.time() if when == 0 else when
        return self.get_next_event("bs", when)

    def get_next_ai(self, when=0):
        when = time.time() if when == 0 else when
        return self.get_next_event("ai", when)


class WeeklyEvent:
    start = 0
    end = 0
    type = ""

    def __init__(self, event_type, start, end):
        self.start = start
        self.end = end
        self.type = event_type

    def is_running(self, when=0):
        when = time.time() if when == 0 else when
        return self.start <= when <= self.end
