# Copyright 2014-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 os
from . import coredata, environment, mesonlib, build, mintro, mlog
from .ast import AstIDGenerator

def add_arguments(parser):
    coredata.register_builtin_arguments(parser)
    parser.add_argument('builddir', nargs='?', default='.')
    parser.add_argument('--clearcache', action='store_true', default=False,
                        help='Clear cached state (e.g. found dependencies)')


def make_lower_case(val):
    if isinstance(val, bool):
        return str(val).lower()
    elif isinstance(val, list):
        return [make_lower_case(i) for i in val]
    else:
        return str(val)


class ConfException(mesonlib.MesonException):
    pass


class Conf:
    def __init__(self, build_dir):
        self.build_dir = os.path.abspath(os.path.realpath(build_dir))
        if 'meson.build' in [os.path.basename(self.build_dir), self.build_dir]:
            self.build_dir = os.path.dirname(self.build_dir)
        self.build = None
        self.max_choices_line_length = 60

        if os.path.isdir(os.path.join(self.build_dir, 'meson-private')):
            self.build = build.load(self.build_dir)
            self.source_dir = self.build.environment.get_source_dir()
            self.coredata = coredata.load(self.build_dir)
            self.default_values_only = False
        elif os.path.isfile(os.path.join(self.build_dir, environment.build_filename)):
            # Make sure that log entries in other parts of meson don't interfere with the JSON output
            mlog.disable()
            self.source_dir = os.path.abspath(os.path.realpath(self.build_dir))
            intr = mintro.IntrospectionInterpreter(self.source_dir, '', 'ninja', visitors = [AstIDGenerator()])
            intr.analyze()
            # Reenable logging just in case
            mlog.enable()
            self.coredata = intr.coredata
            self.default_values_only = True
        else:
            raise ConfException('Directory {} is neither a Meson build directory nor a project source directory.'.format(build_dir))

    def clear_cache(self):
        self.coredata.deps.host.clear()
        self.coredata.deps.build.clear()

    def set_options(self, options):
        self.coredata.set_options(options)

    def save(self):
        # Do nothing when using introspection
        if self.default_values_only:
            return
        # Only called if something has changed so overwrite unconditionally.
        coredata.save(self.coredata, self.build_dir)
        # We don't write the build file because any changes to it
        # are erased when Meson is executed the next time, i.e. when
        # Ninja is run.

    def print_aligned(self, arr):
        if not arr:
            return

        titles = {'name': 'Option', 'descr': 'Description', 'value': 'Current Value', 'choices': 'Possible Values'}
        if self.default_values_only:
            titles['value'] = 'Default Value'

        name_col = [titles['name'], '-' * len(titles['name'])]
        value_col = [titles['value'], '-' * len(titles['value'])]
        choices_col = [titles['choices'], '-' * len(titles['choices'])]
        descr_col = [titles['descr'], '-' * len(titles['descr'])]

        choices_found = False
        for opt in arr:
            name_col.append(opt['name'])
            descr_col.append(opt['descr'])
            if isinstance(opt['value'], list):
                value_col.append('[{0}]'.format(', '.join(make_lower_case(opt['value']))))
            else:
                value_col.append(make_lower_case(opt['value']))
            if opt['choices']:
                choices_found = True
                if isinstance(opt['choices'], list):
                    choices_list = make_lower_case(opt['choices'])
                    current = '['
                    while choices_list:
                        i = choices_list.pop(0)
                        if len(current) + len(i) >= self.max_choices_line_length:
                            choices_col.append(current + ',')
                            name_col.append('')
                            value_col.append('')
                            descr_col.append('')
                            current = ' '
                        if len(current) > 1:
                            current += ', '
                        current += i
                    choices_col.append(current + ']')
                else:
                    choices_col.append(make_lower_case(opt['choices']))
            else:
                choices_col.append('')

        col_widths = (max([len(i) for i in name_col], default=0),
                      max([len(i) for i in value_col], default=0),
                      max([len(i) for i in choices_col], default=0),
                      max([len(i) for i in descr_col], default=0))

        for line in zip(name_col, value_col, choices_col, descr_col):
            if choices_found:
                print('  {0:{width[0]}} {1:{width[1]}} {2:{width[2]}} {3:{width[3]}}'.format(*line, width=col_widths))
            else:
                print('  {0:{width[0]}} {1:{width[1]}} {3:{width[3]}}'.format(*line, width=col_widths))

    def print_options(self, title, options):
        print('\n{}:'.format(title))
        if not options:
            print('  No {}\n'.format(title.lower()))
        arr = []
        for k, o in sorted(options.items()):
            d = o.description
            v = o.printable_value()
            c = o.choices
            arr.append({'name': k, 'descr': d, 'value': v, 'choices': c})
        self.print_aligned(arr)

    def print_conf(self):
        def print_default_values_warning():
            mlog.warning('The source directory instead of the build directory was specified.')
            mlog.warning('Only the default values for the project are printed, and all command line parameters are ignored.')

        if self.default_values_only:
            print_default_values_warning()
            print('')

        print('Core properties:')
        print('  Source dir', self.source_dir)
        if not self.default_values_only:
            print('  Build dir ', self.build_dir)

        dir_option_names = ['bindir',
                            'datadir',
                            'includedir',
                            'infodir',
                            'libdir',
                            'libexecdir',
                            'localedir',
                            'localstatedir',
                            'mandir',
                            'prefix',
                            'sbindir',
                            'sharedstatedir',
                            'sysconfdir']
        test_option_names = ['errorlogs',
                             'stdsplit']
        core_option_names = [k for k in self.coredata.builtins if k not in dir_option_names + test_option_names]

        dir_options = {k: o for k, o in self.coredata.builtins.items() if k in dir_option_names}
        test_options = {k: o for k, o in self.coredata.builtins.items() if k in test_option_names}
        core_options = {k: o for k, o in self.coredata.builtins.items() if k in core_option_names}

        self.print_options('Core options', core_options)
        if self.default_values_only or self.build.environment.is_cross_build():
            self.print_options('Core options (for host machine)', self.coredata.builtins_per_machine.host)
            self.print_options(
                'Core options (for build machine)',
                {'build.' + k: o for k, o in self.coredata.builtins_per_machine.build.items()})
        else:
            self.print_options('Core options', self.coredata.builtins_per_machine.host)
        self.print_options('Backend options', self.coredata.backend_options)
        self.print_options('Base options', self.coredata.base_options)
        if self.default_values_only or self.build.environment.is_cross_build():
            self.print_options('Compiler options (for host machine)', self.coredata.compiler_options.host)
            self.print_options(
                'Compiler options (for build machine)',
                {'build.' + k: o for k, o in self.coredata.compiler_options.build.items()})
        else:
            self.print_options('Compiler options', self.coredata.compiler_options.host)
        self.print_options('Directories', dir_options)
        self.print_options('Project options', self.coredata.user_options)
        self.print_options('Testing options', test_options)

        # Print the warning twice so that the user shouldn't be able to miss it
        if self.default_values_only:
            print('')
            print_default_values_warning()

def run(options):
    coredata.parse_cmd_line_options(options)
    builddir = os.path.abspath(os.path.realpath(options.builddir))
    c = None
    try:
        c = Conf(builddir)
        if c.default_values_only:
            c.print_conf()
            return 0

        save = False
        if len(options.cmd_line_options) > 0:
            c.set_options(options.cmd_line_options)
            coredata.update_cmd_line_file(builddir, options)
            save = True
        elif options.clearcache:
            c.clear_cache()
            save = True
        else:
            c.print_conf()
        if save:
            c.save()
            mintro.update_build_options(c.coredata, c.build.environment.info_dir)
            mintro.write_meson_info_file(c.build, [])
    except ConfException as e:
        print('Meson configurator encountered an error:')
        if c is not None and c.build is not None:
            mintro.write_meson_info_file(c.build, [e])
        raise e
    return 0
