# Copyright (c) 2023 Project CHIP Authors
#
# 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.

# This file contains private utilities for use by the `configure` script.
# It is self-contained and depends only on the Python 3 standard library.
#
# Some unit tests that can be run manually are in configure.impl.test.py.

import collections
import json
import os
import re
import sys
import urllib.request
import zipfile


def download(url, dest):
    urllib.request.urlretrieve(url, dest)


def download_and_extract_zip(url, dest_dir, *member_names):
    file, *_ = urllib.request.urlretrieve(url)
    with zipfile.ZipFile(file) as zip_file:
        for member in zip_file.infolist():
            if member.filename in member_names:
                zip_file.extract(member, dest_dir)


def process_project_args(gn_args_json_file, *params):
    processor = ProjectArgProcessor(gn_args_json_file)
    processor.process_env()
    processor.process_parameters(params)
    for arg, value in processor.args.items():
        info(f" - {arg} = {value}")
        print(f"{arg} = {value}")


def describe_args(gn_args_json_file):
    processor = ProjectArgProcessor(gn_args_json_file)

    # Header / Built-ins handled by process_triplet_parameter
    print("Available configure options and default values:\n"
          "\n"
          "### Target Options\n"
          "\n"
          "--build=...\n"
          "  # host_cpu, host_os: GN built-in\n"
          "  # The system on which the software is being built, as cpu-os or cpu-vendor-os[-abi]\n"
          "\n"
          "--host=...\n"
          "--target=...\n"
          "  # target_cpu, target_os: GN built-in\n"
          "  # The system on which the software will run, as cpu-os or cpu-vendor-os[-abi]\n"
          )

    def describe_group(group, heading):
        if not group:
            return
        print(f"### {heading}\n")
        for arg in sorted(group, key=lambda a: a.alias):
            if arg.type == 'b':
                print(f"--enable-{arg.alias}{'=no' if arg.default == 'false' else ''}")
            else:
                # Abbreviate long list / structs
                default = arg.default if len(arg.default) <= 40 \
                    else '[...]' if arg.type == '[' \
                    else '{...}' if arg.type == '{' \
                    else arg.default
                print(f"--{arg.alias}={default}")
            if arg.source:
                print(f"  # {arg.name}: {arg.source}")
            if arg.comment:
                print("  #", arg.comment.replace("\n", "\n  # "))
            print()

    project, sdk, third_party, overrides = [], [], [], []
    for arg in processor.gn_args.values():
        if (source := arg.source) and arg.alias:
            group = third_party if source.startswith('//third_party/connectedhomeip/third_party/') \
                else sdk if source.startswith('//third_party/connectedhomeip/') \
                else third_party if source.startswith('//third_party/') \
                else overrides if source.startswith('//build_overrides/') \
                else project
            group.append(arg)

    describe_group(project, "Project Options")
    describe_group(sdk, "Matter SDK Options")
    describe_group(overrides, "Build Override Paths")
    describe_group(third_party, "Third-Party Options")


class ProjectArgProcessor:

    class GnArg:
        # Prefixes for mapping between configure parameters and GN arguments (longer prefixes first)
        BOOL_ARG_PREFIXES = ('is_', 'enable_', 'use_',
                             'chip_enable_', 'chip_use_', 'chip_config_', 'chip_',
                             'matter_enable_', 'matter_use_', 'matter_config_', 'matter_', '')
        GENERIC_ARG_PREFIXES = ('chip_config_', 'chip_', 'matter_config_', 'matter_', '')

        ARG_TYPE_TRANS = str.maketrans('"tf0123456789-', 'sbbiiiiiiiiiii')
        DASH_TRANS = str.maketrans('_', '-')

        def __init__(self, data):
            self.name = str(data['name'])
            self.alias = None  # will be set below
            self.default = str(data['default']['value'])
            self.type = self.default[0].translate(self.ARG_TYPE_TRANS)  # 's'tring, 'b'ool, 'i'integer, '[' list, '{' struct
            file = data['default'].get('file', None)
            self.source = f"{file}:{data['default']['line']}" if file else None
            self.comment = str(data.get('comment', '')).strip()

        def alias_candidates(self):
            prefixes = self.BOOL_ARG_PREFIXES if self.type == 'b' else self.GENERIC_ARG_PREFIXES
            return (self.name.removeprefix(p).lower().translate(self.DASH_TRANS) for p in prefixes if self.name.startswith(p))

        def __str__(self):
            return self.name

    args: collections.OrderedDict  # collected arguments
    gn_args: dict[str, GnArg]  # by GN name
    options: dict[str, GnArg]  # by all unique option aliases

    def __init__(self, gn_args_json_file):
        self.args = collections.OrderedDict()

        # Parse `gn args --list --json` output into gn_args
        with open(gn_args_json_file) as fh:
            self.gn_args = {arg.name: arg for arg in (self.GnArg(rec) for rec in json.load(fh))}

        # Count collisions first then index options by all unique aliases
        counts = collections.defaultdict(int)
        for arg in self.gn_args.values():
            for alias in arg.alias_candidates():
                counts[alias] += 1
        self.options = {}
        for arg in self.gn_args.values():
            for alias in arg.alias_candidates():
                if counts[alias] <= 1:
                    self.options[alias] = arg
                    arg.alias = arg.alias or alias  # canonical (shortest unique) alias

    def process_env(self):
        self.add_env_arg('chip_code_pre_generated_directory', 'CHIP_PREGEN_DIR')

        self.add_arg('custom_toolchain', 'custom', required=False)
        self.add_env_arg('target_cc', 'CC', 'cc')
        self.add_env_arg('target_cxx', 'CXX', 'cxx')
        self.add_env_arg('target_ar', 'AR', 'ar')
        self.add_env_arg('target_cflags', 'CPPFLAGS', is_list=True)
        self.add_env_arg('target_cflags_c', 'CFLAGS', is_list=True)
        self.add_env_arg('target_cflags_cc', 'CXXFLAGS', is_list=True)
        self.add_env_arg('target_cflags_objc', 'OBJCFLAGS', is_list=True)
        self.add_env_arg('target_ldflags', 'LDFLAGS', is_list=True)

    def add_arg(self, nameOrArg, value, required=True):
        if arg := self.gn_args.get(nameOrArg, None) if isinstance(nameOrArg, str) else nameOrArg:
            # format strings and booleans as JSON, otherwise pass through as is
            self.args[arg.name] = (json.dumps(value) if arg.type in 'sb' else value)
        elif required:
            fail(f"Project has no build arg '{nameOrArg}'")

    def add_env_arg(self, name, envvar, default=None, is_list=False):
        """Add an argument from an environment variable"""
        if not (value := os.environ.get(envvar, default)):
            return
        if not (arg := self.gn_args.get(name, None)):
            info(f"Warning: Not propagating {envvar}, project has no build arg '{name}'")
            return
        # bypass add_arg() to handle list splitting / formatting directly
        self.args[arg.name] = json.dumps(value if arg.type != '[' else value.split() if is_list else [value])

    def process_triplet_parameter(self, name, value):
        if value is None:
            fail(f"Project option --{name} requires an argument")
        triplet = value.split('-')
        if len(triplet) not in (2, 3, 4):
            fail(f"Project option --{name} argument must be a cpu-os pair or cpu-vendor-os[-abi] triplet")
        prefix = 'host_' if name == 'build' else 'target_'  # "host" has different meanings in GNU and GN!
        self.add_arg(prefix + 'cpu', triplet[0])
        self.add_arg(prefix + 'os', triplet[1 if len(triplet) == 2 else 2])

    def option(self, option):
        """Returns the GnArg for the given option name, or None"""
        if not (arg := self.options.get(option, None)):
            info(f"Warning: Project has no build option '{option}'")
        return arg

    def process_enable_parameter(self, option, value):
        if not (arg := self.option(option.removeprefix('enable-'))):
            return
        if arg.type != 'b':
            fail(f"Project build arg '{arg}' is not a boolean")
        if value != 'no' and value is not None:
            fail(f"Invalid argument for --{option}, must be absent or 'no'")
        self.add_arg(arg, value is None)

    def process_generic_parameter(self, option, value):
        if not (arg := self.option(option)):
            return
        if arg.type == 'b':
            fail(f"Project build arg '{arg}' is a boolean, use --enable-...")
        if value is None:
            fail(f"Project option --{option} requires an argument")
        self.add_arg(arg, value)

    def process_parameter(self, option, value):
        if option in ('build', 'host', 'target'):
            self.process_triplet_parameter(option, value)
        elif option.startswith('enable-'):
            self.process_enable_parameter(option, value)
        else:
            self.process_generic_parameter(option, value)

    def process_parameters(self, params):
        """Process GNU-style configure command line parameters"""
        for param in params:
            match = re.fullmatch(r'--([a-z][a-z0-9-]*)(?:=(.*))?', param)
            if not match:
                fail(f"Invalid argument: '{param}'")
            self.process_parameter(match.group(1), match.group(2))


def info(message):
    print(message, file=sys.stderr)


def fail(message):
    info("Error: " + message)
    sys.exit(1)


if __name__ == "__main__":
    # `configure` invokes the top-level functions in this file by
    # passing the function name and arguments on the command line.
    [_, func, *args] = sys.argv
    globals()[func](*args)
