# SPDX-License-Identifier: Apache-2.0
# Copyright 2012-2021 The Meson development team

from __future__ import annotations

# Work around some pathlib bugs...

from . import _pathlib
import sys
sys.modules['pathlib'] = _pathlib

# This file is an entry point for all commands, including scripts. Include the
# strict minimum python modules for performance reasons.
import os.path
import platform
import importlib
import argparse
import typing as T

from .utils.core import MesonException, MesonBugException
from . import mlog

def errorhandler(e: Exception, command: str) -> int:
    import traceback
    if isinstance(e, MesonException):
        mlog.exception(e)
        logfile = mlog.shutdown()
        if logfile is not None:
            mlog.log("\nA full log can be found at", mlog.bold(logfile))
            contents = mlog.ci_fold_file(logfile, f'CI platform detected, click here for {os.path.basename(logfile)} contents.')
            if contents:
                print(contents)
        if os.environ.get('MESON_FORCE_BACKTRACE'):
            raise e
        return 1
    else:
        # We assume many types of traceback are Meson logic bugs, but most
        # particularly anything coming from the interpreter during `setup`.
        # Some things definitely aren't:
        # - PermissionError is always a problem in the user environment
        # - runpython doesn't run Meson's own code, even though it is
        #   dispatched by our run()
        if os.environ.get('MESON_FORCE_BACKTRACE'):
            raise e
        traceback.print_exc()

        if command == 'runpython':
            return 2
        elif isinstance(e, OSError):
            mlog.exception(Exception("Unhandled python OSError. This is probably not a Meson bug, "
                           "but an issue with your build environment."))
            return e.errno
        else: # Exception
            msg = 'Unhandled python exception'
            if all(getattr(e, a, None) is not None for a in ['file', 'lineno', 'colno']):
                e = MesonBugException(msg, e.file, e.lineno, e.colno) # type: ignore
            else:
                e = MesonBugException(msg)
            mlog.exception(e)
        return 2

# Note: when adding arguments, please also add them to the completion
# scripts in $MESONSRC/data/shell-completions/
class CommandLineParser:
    def __init__(self) -> None:
        # only import these once we do full argparse processing
        from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata, mcompile, mdevenv, mformat
        from .scripts import env2mfile, reprotest
        from .wrap import wraptool
        import shutil

        self.term_width = shutil.get_terminal_size().columns
        self.formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=int(self.term_width / 2), width=self.term_width)

        self.commands: T.Dict[str, argparse.ArgumentParser] = {}
        self.hidden_commands: T.List[str] = []
        self.parser = argparse.ArgumentParser(prog='meson', formatter_class=self.formatter)
        self.subparsers = self.parser.add_subparsers(title='Commands', dest='command',
                                                     description='If no command is specified it defaults to setup command.')
        self.add_command('setup', msetup.add_arguments, msetup.run,
                         help_msg='Configure the project')
        self.add_command('configure', mconf.add_arguments, mconf.run,
                         help_msg='Change project options',)
        self.add_command('dist', mdist.add_arguments, mdist.run,
                         help_msg='Generate release archive',)
        self.add_command('install', minstall.add_arguments, minstall.run,
                         help_msg='Install the project')
        self.add_command('introspect', mintro.add_arguments, mintro.run,
                         help_msg='Introspect project')
        self.add_command('init', minit.add_arguments, minit.run,
                         help_msg='Create a new project')
        self.add_command('test', mtest.add_arguments, mtest.run,
                         help_msg='Run tests')
        self.add_command('wrap', wraptool.add_arguments, wraptool.run,
                         help_msg='Wrap tools')
        self.add_command('subprojects', msubprojects.add_arguments, msubprojects.run,
                         help_msg='Manage subprojects')
        self.add_command('rewrite', lambda parser: rewriter.add_arguments(parser, self.formatter), rewriter.run,
                         help_msg='Modify the project definition')
        self.add_command('compile', mcompile.add_arguments, mcompile.run,
                         help_msg='Build the project')
        self.add_command('devenv', mdevenv.add_arguments, mdevenv.run,
                         help_msg='Run commands in developer environment')
        self.add_command('env2mfile', env2mfile.add_arguments, env2mfile.run,
                         help_msg='Convert current environment to a cross or native file')
        self.add_command('reprotest', reprotest.add_arguments, reprotest.run,
                         help_msg='Test if project builds reproducibly')
        self.add_command('format', mformat.add_arguments, mformat.run, aliases=['fmt'],
                         help_msg='Format meson source file')
        # Add new commands above this line to list them in help command
        self.add_command('help', self.add_help_arguments, self.run_help_command,
                         help_msg='Print help of a subcommand')

        # Hidden commands
        self.add_command('runpython', self.add_runpython_arguments, self.run_runpython_command,
                         help_msg=argparse.SUPPRESS)
        self.add_command('unstable-coredata', munstable_coredata.add_arguments, munstable_coredata.run,
                         help_msg=argparse.SUPPRESS)

    def add_command(self, name: str, add_arguments_func: T.Callable[[argparse.ArgumentParser], None],
                    run_func: T.Callable[[argparse.Namespace], int], help_msg: str, aliases: T.List[str] = None) -> None:
        aliases = aliases or []
        # FIXME: Cannot have hidden subparser:
        # https://bugs.python.org/issue22848
        if help_msg == argparse.SUPPRESS:
            p = argparse.ArgumentParser(prog='meson ' + name, formatter_class=self.formatter)
            self.hidden_commands.append(name)
        else:
            p = self.subparsers.add_parser(name, help=help_msg, aliases=aliases, formatter_class=self.formatter)
        add_arguments_func(p)
        p.set_defaults(run_func=run_func)
        for i in [name] + aliases:
            self.commands[i] = p

    def add_runpython_arguments(self, parser: argparse.ArgumentParser) -> None:
        parser.add_argument('-c', action='store_true', dest='eval_arg', default=False)
        parser.add_argument('--version', action='version', version=platform.python_version())
        parser.add_argument('script_file')
        parser.add_argument('script_args', nargs=argparse.REMAINDER)

    def run_runpython_command(self, options: argparse.Namespace) -> int:
        sys.argv[1:] = options.script_args
        if options.eval_arg:
            exec(options.script_file)
        else:
            import runpy
            sys.path.insert(0, os.path.dirname(options.script_file))
            runpy.run_path(options.script_file, run_name='__main__')
        return 0

    def add_help_arguments(self, parser: argparse.ArgumentParser) -> None:
        parser.add_argument('command', nargs='?', choices=list(self.commands.keys()))

    def run_help_command(self, options: argparse.Namespace) -> int:
        if options.command:
            self.commands[options.command].print_help()
        else:
            self.parser.print_help()
        return 0

    def run(self, args: T.List[str]) -> int:
        implicit_setup_command_notice = False
        # If first arg is not a known command, assume user wants to run the setup
        # command.
        known_commands = list(self.commands.keys()) + ['-h', '--help']
        if not args or args[0] not in known_commands:
            implicit_setup_command_notice = True
            args = ['setup'] + args

        # Hidden commands have their own parser instead of using the global one
        if args[0] in self.hidden_commands:
            command = args[0]
            parser = self.commands[command]
            args = args[1:]
        else:
            parser = self.parser
            command = None

        from . import mesonlib
        args = mesonlib.expand_arguments(args)
        options = parser.parse_args(args)

        if command is None:
            command = options.command

        # Bump the version here in order to add a pre-exit warning that we are phasing out
        # support for old python. If this is already the oldest supported version, then
        # this can never be true and does nothing.
        pending_python_deprecation_notice = \
            command in {'setup', 'compile', 'test', 'install'} and sys.version_info < (3, 7)

        try:
            return options.run_func(options)
        except Exception as e:
            return errorhandler(e, command)
        finally:
            if implicit_setup_command_notice:
                mlog.warning('Running the setup command as `meson [options]` instead of '
                             '`meson setup [options]` is ambiguous and deprecated.', fatal=False)
            if pending_python_deprecation_notice:
                mlog.notice('You are using Python 3.6 which is EOL. Starting with v0.62.0, '
                            'Meson will require Python 3.7 or newer', fatal=False)
            mlog.shutdown()

def run_script_command(script_name: str, script_args: T.List[str]) -> int:
    # Map script name to module name for those that doesn't match
    script_map = {'exe': 'meson_exe',
                  'install': 'meson_install',
                  'delsuffix': 'delwithsuffix',
                  'gtkdoc': 'gtkdochelper',
                  'hotdoc': 'hotdochelper',
                  'regencheck': 'regen_checker'}
    module_name = script_map.get(script_name, script_name)

    try:
        module = importlib.import_module('mesonbuild.scripts.' + module_name)
    except ModuleNotFoundError as e:
        mlog.exception(e)
        return 1

    try:
        return module.run(script_args)
    except MesonException as e:
        mlog.error(f'Error in {script_name} helper script:')
        mlog.exception(e)
        return 1

def ensure_stdout_accepts_unicode() -> None:
    if sys.stdout.encoding and not sys.stdout.encoding.upper().startswith('UTF-'):
        sys.stdout.reconfigure(errors='surrogateescape') # type: ignore[attr-defined]

def set_meson_command(mainfile: str) -> None:
    # Set the meson command that will be used to run scripts and so on
    from . import mesonlib
    mesonlib.set_meson_command(mainfile)

def validate_original_args(args):
    import mesonbuild.options
    import itertools

    def has_startswith(coll, target):
        for entry in coll:
            if entry.startswith(target):
                return True
        return False
    #ds = [x for x in args if x.startswith('-D')]
    #longs = [x for x in args if x.startswith('--')]
    for optionkey in itertools.chain(mesonbuild.options.BUILTIN_DIR_OPTIONS, mesonbuild.options.BUILTIN_CORE_OPTIONS):
        longarg = mesonbuild.options.argparse_name_to_arg(optionkey.name)
        shortarg = f'-D{optionkey.name}'
        if has_startswith(args, longarg) and has_startswith(args, shortarg):
            sys.exit(
                f'Got argument {optionkey.name} as both {shortarg} and {longarg}. Pick one.')


def run(original_args: T.List[str], mainfile: str) -> int:
    if os.environ.get('MESON_SHOW_DEPRECATIONS'):
        # workaround for https://bugs.python.org/issue34624
        import warnings
        for typ in [DeprecationWarning, SyntaxWarning, FutureWarning, PendingDeprecationWarning]:
            warnings.filterwarnings('error', category=typ, module='mesonbuild')
        warnings.filterwarnings('ignore', message=".*importlib-resources.*")

    if sys.version_info >= (3, 10) and os.environ.get('MESON_RUNNING_IN_PROJECT_TESTS'):
        # workaround for https://bugs.python.org/issue34624
        import warnings
        warnings.filterwarnings('error', category=EncodingWarning, module='mesonbuild')
        # python 3.11 adds a warning that in 3.15, UTF-8 mode will be default.
        # This is fantastic news, we'd love that. Less fantastic: this warning is silly,
        # we *want* these checks to be affected. Plus, the recommended alternative API
        # would (in addition to warning people when UTF-8 mode removed the problem) also
        # require using a minimum python version of 3.11 (in which the warning was added)
        # or add verbose if/else soup.
        warnings.filterwarnings('ignore', message="UTF-8 Mode affects .*getpreferredencoding", category=EncodingWarning)

    # Meson gets confused if stdout can't output Unicode, if the
    # locale isn't Unicode, just force stdout to accept it. This tries
    # to emulate enough of PEP 540 to work elsewhere.
    ensure_stdout_accepts_unicode()

    # https://github.com/mesonbuild/meson/issues/3653
    if sys.platform == 'cygwin' and os.environ.get('MSYSTEM', '') not in ['MSYS', '']:
        mlog.error('This python3 seems to be msys/python on MSYS2 Windows, but you are in a MinGW environment')
        mlog.error('Please install it via https://packages.msys2.org/base/mingw-w64-python')
        return 2

    args = original_args[:]

    # Special handling of internal commands called from backends, they don't
    # need to go through argparse.
    if len(args) >= 2 and args[0] == '--internal':
        if args[1] == 'regenerate':
            set_meson_command(mainfile)
            from . import msetup
            try:
                return msetup.run(['--reconfigure'] + args[2:])
            except Exception as e:
                return errorhandler(e, 'setup')
        else:
            return run_script_command(args[1], args[2:])

    set_meson_command(mainfile)
    validate_original_args(args)
    return CommandLineParser().run(args)

def main() -> int:
    # Always resolve the command path so Ninja can find it for regen, tests, etc.
    if getattr(sys, 'frozen', False):
        assert os.path.isabs(sys.executable)
        launcher = sys.executable
    else:
        launcher = os.path.abspath(sys.argv[0])
    return run(sys.argv[1:], launcher)

if __name__ == '__main__':
    sys.exit(main())
