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

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:
        for member in zip.infolist():
            if member.filename in member_names:
                zip.extract(member, dest_dir)


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


class ProjectArgProcessor:
    # Prefixes to try when mapping parameters to GN arguments
    BOOL_ARG_PREFIXES = ('is_', 'enable_', 'use_',
                         'chip_', 'chip_enable_', 'chip_use_', 'chip_config_',
                         'matter_', 'matter_enable_', 'matter_use_', 'matter_config_')
    GENERIC_ARG_PREFIXES = ('chip_', 'chip_config_', 'matter_', 'matter_config_')

    gn_args = {}  # GN arg -> type ('s'tring, 'b'ool, 'i'integer, '[' list, '{' struct)
    args = collections.OrderedDict()  # collected arguments

    def __init__(self, gn_args_json_file):
        # Parse `gn args --list --json` output and derive arg types from default values
        argtype = str.maketrans('"tf0123456789', 'sbbiiiiiiiiii')
        with open(gn_args_json_file) as fh:
            for arg in json.load(fh):
                self.gn_args[arg['name']] = arg['default']['value'][0].translate(argtype)

    def process_defaults(self):
        self.add_default('custom_toolchain', 'custom')

    def process_env(self):
        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', list=True)
        self.add_env_arg('target_cflags_c', 'CFLAGS', list=True)
        self.add_env_arg('target_cflags_cc', 'CXXFLAGS', list=True)
        self.add_env_arg('target_cflags_objc', 'OBJCFLAGS', list=True)
        self.add_env_arg('target_ldflags', 'LDFLAGS', list=True)

    def add_arg(self, arg, value):
        # format strings and booleans as JSON, otherwise pass through as is
        self.args[arg] = (json.dumps(value) if self.gn_args.get(arg, 's') in 'sb' else value)

    def add_default(self, arg, value):
        """Add an argument, if supported by the GN build"""
        if arg in self.gn_args:
            self.add_arg(arg, value)

    def add_env_arg(self, arg, envvar, default=None, list=False):
        """Add an argument from an environment variable"""
        value = os.environ.get(envvar, default)
        if not value:
            return
        type = self.gn_args.get(arg, None)
        if not type:
            info("Warning: Not propagating %s, project has no build arg '%s'" % (envvar, arg))
            return
        self.args[arg] = json.dumps(value if type != '[' else value.split() if list else [value])

    def gn_arg(self, name, prefixes=(), type=None):
        """Finds the GN argument corresponding to a parameter name"""
        arg = name.translate(str.maketrans('-', '_'))
        candidates = [p + arg for p in (('',) + prefixes) if (p + arg) in self.gn_args]
        preferred = [c for c in candidates if self.gn_args[c] == type] if type else []
        match = next(iter(preferred + candidates), None)
        if not match:
            info("Warning: Project has no build arg '%s'" % arg)
        return match

    def process_triplet_parameter(self, name, value):
        if value is None:
            fail("Project option --%s requires an argument" % name)
        triplet = value.split('-')
        if len(triplet) not in (2, 3, 4):
            fail("Project option --%s argument must be a cpu-vendor-os[-abi] triplet" % name)
        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 process_enable_parameter(self, name, value):
        arg = self.gn_arg(name[len('enable-'):], self.BOOL_ARG_PREFIXES, 'b')
        if not arg:
            return
        if self.gn_args[arg] != 'b':
            fail("Project build arg '%s' is not a boolean" % arg)
        if value != 'no' and value is not None:
            fail("Invalid argument for --%s, must be absent or 'no'" % name)
        self.add_arg(arg, value is None)

    def process_generic_parameter(self, name, value):
        arg = self.gn_arg(name, self.GENERIC_ARG_PREFIXES)
        if not arg:
            return
        if self.gn_args[arg] == 'b':
            fail("Project build arg '%s' is a boolean, use --enable-..." % arg)
        if value is None:
            fail("Project option --%s requires an argument" % name)
        self.add_arg(arg, value)

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

    def process_parameters(self, args):
        """Process GNU-style configure command line parameters"""
        for arg in args:
            match = re.fullmatch(r'--([a-z][a-z0-9-]*)(?:=(.*))?', arg)
            if not match:
                fail("Invalid argument: '%s'" % arg)
            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)


# `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)
