import json
import os
import sys
import types
from sysconfig import (
    _ALWAYS_STR,
    _PYTHON_BUILD,
    _get_sysconfigdata_name,
    get_config_h_filename,
    get_config_var,
    get_config_vars,
    get_default_scheme,
    get_makefile_filename,
    get_paths,
    get_platform,
    get_python_version,
    parse_config_h,
)


# Regexes needed for parsing Makefile (and similar syntaxes,
# like old-style Setup files).
_variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)"
_findvar_rx = (r"\$(\([A-Za-z][A-Za-z0-9_]*\)"
                 r"|\{[A-Za-z][A-Za-z0-9_]*\}"
                 r"|\$?)")


def _parse_makefile(filename, vars=None, keep_unresolved=True):
    """Parse a Makefile-style file.

    A dictionary containing name/value pairs is returned.  If an
    optional dictionary is passed in as the second argument, it is
    used instead of a new dictionary.
    """
    import re

    if vars is None:
        vars = {}
    done = {}
    notdone = {}

    with open(filename, encoding=sys.getfilesystemencoding(),
              errors="surrogateescape") as f:
        lines = f.readlines()

    for line in lines:
        if line.startswith('#') or line.strip() == '':
            continue
        m = re.match(_variable_rx, line)
        if m:
            n, v = m.group(1, 2)
            notdone[n] = v.strip()

    # Variables with a 'PY_' prefix in the makefile. These need to
    # be made available without that prefix through sysconfig.
    # Special care is needed to ensure that variable expansion works, even
    # if the expansion uses the name without a prefix.
    renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')

    def resolve_var(name):
        def repl(m):
            n = m[1]
            if n == '$':
                return '$'
            elif n == '':
                # bogus variable reference (e.g. "prefix=$/opt/python")
                if keep_unresolved:
                    return m[0]
                raise ValueError
            elif n[0] == '(' and n[-1] == ')':
                n = n[1:-1]
            elif n[0] == '{' and n[-1] == '}':
                n = n[1:-1]

            if n in done:
                return str(done[n])
            elif n in notdone:
                return str(resolve_var(n))
            elif n in os.environ:
                # do it like make: fall back to environment
                return os.environ[n]
            elif n in renamed_variables:
                if name.startswith('PY_') and name[3:] in renamed_variables:
                    return ""
                n = 'PY_' + n
                if n in notdone:
                    return str(resolve_var(n))
                else:
                    assert n not in done
                    return ""
            else:
                done[n] = ""
                return ""

        assert name not in done
        done[name] = ""
        try:
            value = re.sub(_findvar_rx, repl, notdone[name])
        except ValueError:
            del done[name]
            return ""
        value = value.strip()
        if name not in _ALWAYS_STR:
            try:
                value = int(value)
            except ValueError:
                pass
        done[name] = value
        if name.startswith('PY_') and name[3:] in renamed_variables:
            name = name[3:]
            if name not in done:
                done[name] = value
        return value

    for n in notdone:
        if n not in done:
            resolve_var(n)

    # strip spurious spaces
    for k, v in done.items():
        if isinstance(v, str):
            done[k] = v.strip()

    # save the results in the global dictionary
    vars.update(done)
    return vars


def _print_config_dict(d, stream):
    print ("{", file=stream)
    for k, v in sorted(d.items()):
        print(f"    {k!r}: {v!r},", file=stream)
    print ("}", file=stream)


def _get_pybuilddir():
    pybuilddir = f'build/lib.{get_platform()}-{get_python_version()}'
    if get_config_var('Py_DEBUG') == '1':
        pybuilddir += '-pydebug'
    return pybuilddir


def _get_json_data_name():
    name = _get_sysconfigdata_name()
    assert name.startswith('_sysconfigdata')
    return name.replace('_sysconfigdata', '_sysconfig_vars') + '.json'


def _generate_posix_vars():
    """Generate the Python module containing build-time variables."""
    vars = {}
    # load the installed Makefile:
    makefile = get_makefile_filename()
    try:
        _parse_makefile(makefile, vars)
    except OSError as e:
        msg = f"invalid Python installation: unable to open {makefile}"
        if hasattr(e, "strerror"):
            msg = f"{msg} ({e.strerror})"
        raise OSError(msg)
    # load the installed pyconfig.h:
    config_h = get_config_h_filename()
    try:
        with open(config_h, encoding="utf-8") as f:
            parse_config_h(f, vars)
    except OSError as e:
        msg = f"invalid Python installation: unable to open {config_h}"
        if hasattr(e, "strerror"):
            msg = f"{msg} ({e.strerror})"
        raise OSError(msg)
    # On AIX, there are wrong paths to the linker scripts in the Makefile
    # -- these paths are relative to the Python source, but when installed
    # the scripts are in another directory.
    if _PYTHON_BUILD:
        vars['BLDSHARED'] = vars['LDSHARED']

    name = _get_sysconfigdata_name()

    # There's a chicken-and-egg situation on OS X with regards to the
    # _sysconfigdata module after the changes introduced by #15298:
    # get_config_vars() is called by get_platform() as part of the
    # `make pybuilddir.txt` target -- which is a precursor to the
    # _sysconfigdata.py module being constructed.  Unfortunately,
    # get_config_vars() eventually calls _init_posix(), which attempts
    # to import _sysconfigdata, which we won't have built yet.  In order
    # for _init_posix() to work, if we're on Darwin, just mock up the
    # _sysconfigdata module manually and populate it with the build vars.
    # This is more than sufficient for ensuring the subsequent call to
    # get_platform() succeeds.
    # GH-127178: Since we started generating a .json file, we also need this to
    #            be able to run sysconfig.get_config_vars().
    module = types.ModuleType(name)
    module.build_time_vars = vars
    sys.modules[name] = module

    pybuilddir = _get_pybuilddir()
    os.makedirs(pybuilddir, exist_ok=True)
    destfile = os.path.join(pybuilddir, name + '.py')

    with open(destfile, 'w', encoding='utf8') as f:
        f.write('# system configuration generated and used by'
                ' the sysconfig module\n')
        f.write('build_time_vars = ')
        _print_config_dict(vars, stream=f)

    print(f'Written {destfile}')

    install_vars = get_config_vars()
    # Fix config vars to match the values after install (of the default environment)
    install_vars['projectbase'] = install_vars['BINDIR']
    install_vars['srcdir'] = install_vars['LIBPL']
    # Write a JSON file with the output of sysconfig.get_config_vars
    jsonfile = os.path.join(pybuilddir, _get_json_data_name())
    with open(jsonfile, 'w') as f:
        json.dump(install_vars, f, indent=2)

    print(f'Written {jsonfile}')

    # Create file used for sys.path fixup -- see Modules/getpath.c
    with open('pybuilddir.txt', 'w', encoding='utf8') as f:
        f.write(pybuilddir)


def _print_dict(title, data):
    for index, (key, value) in enumerate(sorted(data.items())):
        if index == 0:
            print(f'{title}: ')
        print(f'\t{key} = "{value}"')


def _main():
    """Display all information sysconfig detains."""
    if '--generate-posix-vars' in sys.argv:
        _generate_posix_vars()
        return
    print(f'Platform: "{get_platform()}"')
    print(f'Python version: "{get_python_version()}"')
    print(f'Current installation scheme: "{get_default_scheme()}"')
    print()
    _print_dict('Paths', get_paths())
    print()
    _print_dict('Variables', get_config_vars())


if __name__ == '__main__':
    try:
        _main()
    except BrokenPipeError:
        pass
