import importlib.util
import re

import mucus.exception


class Command:
    def __call__(self, **kwargs):
        pass


class Loader:
    def __init__(self, line=None, name=None, args=None, aliases=None):
        if aliases is None:
            aliases = {}

        if line is not None:
            try:
                line = aliases[line]
            except KeyError:
                pass

            match = re.match(r'^\s*([A-Za-z0-9_-]+)(.*)', line)
            if match is None:
                raise mucus.exception.NoSuchCommand

            name = match.group(1).replace('-', '_')
            args = match.group(2).strip()

        if name is None:
            raise mucus.exception.NoSuchCommand

        try:
            name = aliases[name]
        except KeyError:
            pass

        try:
            self.mod = self.import_module('.' + name, 'mucus.commands')
        except ModuleNotFoundError as e:
            raise mucus.exception.NoSuchCommand(e)

        self.cmd = self.mod.Command()
        self.name = name
        self.args = args

    def import_module(self, name, package=None):
        spec = importlib.util.find_spec(name, package)
        if spec is None:
            raise ModuleNotFoundError(name)
        loader = importlib.util.LazyLoader(spec.loader)
        spec.loader = loader
        module = importlib.util.module_from_spec(spec)
        loader.exec_module(module)
        return module


class Runner:
    def __init__(self, loader, context):
        self.loader = loader
        self.context = context

    def __call__(self):
        return self.loader.cmd(**self.context)
