# Copyright 2019 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.


from . import coredata as cdata
from .mesonlib import MachineChoice, OptionKey

import os.path
import pprint
import textwrap

def add_arguments(parser):
    parser.add_argument('--all', action='store_true', dest='all', default=False,
                        help='Show data not used by current backend.')

    parser.add_argument('builddir', nargs='?', default='.', help='The build directory')


def dump_compilers(compilers):
    for lang, compiler in compilers.items():
        print('  ' + lang + ':')
        print('      Id: ' + compiler.id)
        print('      Command: ' + ' '.join(compiler.exelist))
        if compiler.full_version:
            print('      Full version: ' + compiler.full_version)
        if compiler.version:
            print('      Detected version: ' + compiler.version)


def dump_guids(d):
    for name, value in d.items():
        print('  ' + name + ': ' + value)


def run(options):
    datadir = 'meson-private'
    if options.builddir is not None:
        datadir = os.path.join(options.builddir, datadir)
    if not os.path.isdir(datadir):
        print('Current directory is not a build dir. Please specify it or '
              'change the working directory to it.')
        return 1

    all_backends = options.all

    print('This is a dump of the internal unstable cache of meson. This is for debugging only.')
    print('Do NOT parse, this will change from version to version in incompatible ways')
    print('')

    coredata = cdata.load(options.builddir)
    backend = coredata.get_option(OptionKey('backend'))
    for k, v in sorted(coredata.__dict__.items()):
        if k in ('backend_options', 'base_options', 'builtins', 'compiler_options', 'user_options'):
            # use `meson configure` to view these
            pass
        elif k in ['install_guid', 'test_guid', 'regen_guid']:
            if all_backends or backend.startswith('vs'):
                print(k + ': ' + v)
        elif k == 'target_guids':
            if all_backends or backend.startswith('vs'):
                print(k + ':')
                dump_guids(v)
        elif k in ['lang_guids']:
            if all_backends or backend.startswith('vs') or backend == 'xcode':
                print(k + ':')
                dump_guids(v)
        elif k == 'meson_command':
            if all_backends or backend.startswith('vs'):
                print('Meson command used in build file regeneration: ' + ' '.join(v))
        elif k == 'pkgconf_envvar':
            print('Last seen PKGCONFIG environment variable value: ' + v)
        elif k == 'version':
            print('Meson version: ' + v)
        elif k == 'cross_files':
            if v:
                print('Cross File: ' + ' '.join(v))
        elif k == 'config_files':
            if v:
                print('Native File: ' + ' '.join(v))
        elif k == 'compilers':
            for for_machine in MachineChoice:
                print('Cached {} machine compilers:'.format(
                    for_machine.get_lower_case_name()))
                dump_compilers(v[for_machine])
        elif k == 'deps':
            def print_dep(dep_key, dep):
                print('  ' + dep_key[0] + ": ")
                print('      compile args: ' + repr(dep.get_compile_args()))
                print('      link args: ' + repr(dep.get_link_args()))
                if dep.get_sources():
                    print('      sources: ' + repr(dep.get_sources()))
                print('      version: ' + repr(dep.get_version()))

            for for_machine in iter(MachineChoice):
                items_list = list(sorted(v[for_machine].items()))
                if items_list:
                    print('Cached dependencies for {} machine' % for_machine.get_lower_case_name())
                    for dep_key, deps in items_list:
                        for dep in deps:
                            print_dep(dep_key, dep)
        else:
            print(k + ':')
            print(textwrap.indent(pprint.pformat(v), '  '))
