# Copyright 2012-2016 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import sys
import os.path
import importlib
import traceback
import argparse

from . import mesonlib
from . import mlog
from . import mconf, minit, minstall, mintro, msetup, mtest, rewriter
from .mesonlib import MesonException
from .environment import detect_msys2_arch
from .wrap import wraptool


class CommandLineParser:
    def __init__(self):
        self.commands = {}
        self.hidden_commands = []
        self.parser = argparse.ArgumentParser(prog='meson')
        self.subparsers = self.parser.add_subparsers(title='Commands',
                                                     description='If no command is specified it defaults to setup command.')
        self.add_command('setup', msetup.add_arguments, msetup.run,
                         help='Configure the project')
        self.add_command('configure', mconf.add_arguments, mconf.run,
                         help='Change project options',)
        self.add_command('install', minstall.add_arguments, minstall.run,
                         help='Install the project')
        self.add_command('introspect', mintro.add_arguments, mintro.run,
                         help='Introspect project')
        self.add_command('init', minit.add_arguments, minit.run,
                         help='Create a new project')
        self.add_command('test', mtest.add_arguments, mtest.run,
                         help='Run tests')
        self.add_command('wrap', wraptool.add_arguments, wraptool.run,
                         help='Wrap tools')
        self.add_command('help', self.add_help_arguments, self.run_help_command,
                         help='Print help of a subcommand')

        # Hidden commands
        self.add_command('rewrite', rewriter.add_arguments, rewriter.run,
                         help=argparse.SUPPRESS)
        self.add_command('runpython', self.add_runpython_arguments, self.run_runpython_command,
                         help=argparse.SUPPRESS)

    def add_command(self, name, add_arguments_func, run_func, help):
        # FIXME: Cannot have hidden subparser:
        # https://bugs.python.org/issue22848
        if help == argparse.SUPPRESS:
            p = argparse.ArgumentParser(prog='meson ' + name)
            self.hidden_commands.append(name)
        else:
            p = self.subparsers.add_parser(name, help=help)
        add_arguments_func(p)
        p.set_defaults(run_func=run_func)
        self.commands[name] = p

    def add_runpython_arguments(self, parser):
        parser.add_argument('script_file')
        parser.add_argument('script_args', nargs=argparse.REMAINDER)

    def run_runpython_command(self, options):
        import runpy
        sys.argv[1:] = options.script_args
        runpy.run_path(options.script_file, run_name='__main__')
        return 0

    def add_help_arguments(self, parser):
        parser.add_argument('command', nargs='?')

    def run_help_command(self, options):
        if options.command:
            self.commands[options.command].print_help()
        else:
            self.parser.print_help()
        return 0

    def run(self, args):
        # 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 len(args) == 0 or args[0] not in known_commands:
            args = ['setup'] + args

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

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

        try:
            return options.run_func(options)
        except MesonException as e:
            mlog.exception(e)
            logfile = mlog.shutdown()
            if logfile is not None:
                mlog.log("\nA full log can be found at", mlog.bold(logfile))
            if os.environ.get('MESON_FORCE_BACKTRACE'):
                raise
            return 1
        except Exception as e:
            if os.environ.get('MESON_FORCE_BACKTRACE'):
                raise
            traceback.print_exc()
            return 2
        finally:
            mlog.shutdown()

def run_script_command(script_name, script_args):
    # 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('Error in {} helper script:'.format(script_name))
        mlog.exception(e)
        return 1

def run(original_args, mainfile):
    if sys.version_info < (3, 5):
        print('Meson works correctly only with python 3.5+.')
        print('You have python %s.' % sys.version)
        print('Please update your environment')
        return 1

    # https://github.com/mesonbuild/meson/issues/3653
    if sys.platform.lower() == 'msys':
        mlog.error('This python3 seems to be msys/python on MSYS2 Windows, which is known to have path semantics incompatible with Meson')
        msys2_arch = detect_msys2_arch()
        if msys2_arch:
            mlog.error('Please install and use mingw-w64-i686-python3 and/or mingw-w64-x86_64-python3 with Pacman')
        else:
            mlog.error('Please download and use Python as detailed at: https://mesonbuild.com/Getting-meson.html')
        return 2

    # Set the meson command that will be used to run scripts and so on
    mesonlib.set_meson_command(mainfile)

    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':
            # Rewrite "meson --internal regenerate" command line to
            # "meson --reconfigure"
            args = ['--reconfigure'] + args[2:]
        else:
            return run_script_command(args[1], args[2:])

    return CommandLineParser().run(args)

def main():
    # Always resolve the command path so Ninja can find it for regen, tests, etc.
    if 'meson.exe' in sys.executable:
        assert(os.path.isabs(sys.executable))
        launcher = sys.executable
    else:
        launcher = os.path.realpath(sys.argv[0])
    return run(sys.argv[1:], launcher)

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