import io
import os
import contextlib
import importlib.util
import modules.errors as errors
from installer import setup_logging, args


preloaded = []
debug = os.environ.get('SD_SCRIPT_DEBUG', None)


def load_module(path):
    module_spec = importlib.util.spec_from_file_location(os.path.basename(path), path)
    module = importlib.util.module_from_spec(module_spec)
    if args.profile:
        import cProfile
        pr = cProfile.Profile()
        pr.enable()
    try:
        if '/sd-extension-' in path or '/Lora' in path: # safe extensions without stdout intercept
            module_spec.loader.exec_module(module)
        else:
            if debug:
                module_spec.loader.exec_module(module)
                stdout = io.StringIO()
            else:
                with contextlib.redirect_stdout(io.StringIO()) as stdout:
                    module_spec.loader.exec_module(module)
            setup_logging() # reset since scripts can hijaack logging
            for line in stdout.getvalue().splitlines():
                if len(line) > 0:
                    errors.log.info(f"Extension: script='{os.path.relpath(path)}' {line.strip()}")
    except Exception as e:
        errors.display(e, f'Module load: {path}')
    if args.profile:
        errors.profile(pr, f'Scripts: {path}')
    return module


def preload_extensions(extensions_dir, parser):
    if not os.path.isdir(extensions_dir):
        return
    for dirname in sorted(os.listdir(extensions_dir)):
        if dirname in preloaded:
            continue
        preloaded.append(dirname)
        preload_script = os.path.join(extensions_dir, dirname, "preload.py")
        if not os.path.isfile(preload_script):
            continue
        try:
            module = load_module(preload_script)
            if hasattr(module, 'preload'):
                module.preload(parser)
        except Exception as e:
            errors.display(e, f'Extension preload: {preload_script}')
