#    Friendly Telegram (telegram userbot)
#    Copyright (C) 2018-2019 The Authors

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

#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.

#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <https://www.gnu.org/licenses/>.

import sys
import logging

from importlib.abc import Loader, MetaPathFinder
from importlib.machinery import ModuleSpec

from .raphielgang import RaphielgangConfig, RaphielgangEvents, RaphielgangDatabase
from .uniborg import UniborgUtil, Uniborg


# When a name is matched, the import is overriden, and our custom object is returned
MODULES = {"userbot": RaphielgangConfig, "userbot.events": RaphielgangEvents,
           "userbot.modules": RaphielgangConfig, "userbot.modules.dbhelper": RaphielgangDatabase, "uniborg": Uniborg,
           "uniborg.util": UniborgUtil}


class BotCompat(MetaPathFinder, Loader):  # pylint: disable=W0223 # It's wrong - https://kutt.it/hkjRb9
    """importlib Loader that loads the classes in MODULES under their pseudonyms"""
    def __init__(self, clients):
        self.clients = clients
        self.created = []

    def find_spec(self, fullname, path, target=None):
        """https://docs.python.org/3.7/library/importlib.html#importlib.abc.MetaPathFinder.find_spec"""
        if fullname in MODULES:
            return ModuleSpec(fullname, self)

    def create_module(self, spec):
        """https://docs.python.org/3.7/library/importlib.html#importlib.abc.Loader.create_module"""
        ret = MODULES[spec.name](self.clients)
        self.created += [ret]
        return ret

    def exec_module(self, module):
        """https://docs.python.org/3.7/library/importlib.html#importlib.abc.Loader.exec_module"""
        module.__path__ = []

    async def client_ready(self, client):
        """Signal all mods that client_ready()"""
        self.clients += [client]
        for mod in self.created:
            try:
                await mod.client_ready(client)
            except BaseException:
                logging.exception("Failed to send client_ready to compat layer " + repr(mod))


def activate(clients):
    """Activate the compat layer"""
    compatlayer = BotCompat(clients)
    sys.meta_path.insert(0, compatlayer)
    return compatlayer