# Copyright 2025 The Pigweed 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
#
#     https://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 argparse
import pathlib
import sys
import kconfiglib


def write_kconfig_build_file(
    ostream,
    kconfig: kconfiglib.Kconfig,
) -> None:
    ostream.write("""load("@bazel_skylib//rules:common_settings.bzl",
    "bool_flag",
    "int_flag",
    "string_flag",
)

package(default_visibility = ["//visibility:public"])
""")
    for sym_name, sym in kconfig.syms.items():
        if sym is None or sym.type == kconfiglib.UNKNOWN:
            continue
        for sym_str in str(sym).splitlines():
            ostream.write(f"# {sym_str}\n")
        if sym.type == kconfiglib.INT or sym.type == kconfiglib.HEX:
            ostream.write(f"""int_flag(
    name = "CONFIG_{sym_name}",
    build_setting_default=0,
    visibility = ["//visibility:public"],
)
""")
        elif sym.type == kconfiglib.BOOL:
            ostream.write(f"""bool_flag(
    name = "CONFIG_{sym_name}",
    build_setting_default=False,
    visibility = ["//visibility:public"],
)
config_setting(
    name = "CONFIG_{sym_name}=true",
    flag_values = {{
        ":CONFIG_{sym_name}": "true",
    }},
)
""")
        elif sym.type == kconfiglib.STRING:
            ostream.write(f"""string_flag(
    name = "CONFIG_{sym_name}",
    build_setting_default="",
    visibility = ["//visibility:public"],
)
""")


def write_project_build_file(
    ostream,
    kconfig: kconfiglib.Kconfig,
) -> None:
    ostream.write("KCONFIG_FLAGS = [\n")
    for sym in kconfig.unique_defined_syms:
        if sym is None or sym.type == kconfiglib.UNKNOWN:
            continue

        name = f"@kconfig//:CONFIG_{sym.name}"
        if sym.type == kconfiglib.INT or sym.type == kconfiglib.HEX:
            value = sym.str_value
            if value == "":
                value = "0"
        elif sym.type == kconfiglib.BOOL:
            value = "true" if sym.str_value == 'y' else "false"
        elif sym.type == kconfiglib.STRING:
            value = f'\\"{sym.str_value}\\"'
        else:
            raise RuntimeError(f"Unsupported symbol type: {sym.type}")
        ostream.write(f"        \"--{name}={value}\",\n")
    ostream.write("]\n")


# Creates a list of options from Kconfig symbols without concerning their
# values in a project.
def generate_kconfig_build_file(
    kconfig_path: pathlib.Path,
    out: pathlib.Path | None,
) -> None:
    print("Loading Kconfig file: " + str(kconfig_path))
    kconfig = kconfiglib.Kconfig(filename=kconfig_path)
    if out:
        with open(out, "w", encoding="utf-8") as f:
            write_kconfig_build_file(ostream=f, kconfig=kconfig)
    else:
        write_kconfig_build_file(ostream=sys.stdout, kconfig=kconfig)


def generate_project_build_file(
    kconfig_path: pathlib.Path,
    project_path: pathlib.Path,
    extra_conf_files: list[pathlib.Path],
    out: pathlib.Path | None,
) -> None:
    print("Loading Kconfig file: " + str(kconfig_path))
    kconfig = kconfiglib.Kconfig(filename=kconfig_path)
    kconfig.load_config(filename=project_path)
    for conf_file in extra_conf_files:
        print(kconfig.load_config(conf_file, replace=False))
    if out:
        with open(out, "w", encoding="utf-8") as f:
            write_project_build_file(ostream=f, kconfig=kconfig)
    else:
        write_project_build_file(ostream=sys.stdout, kconfig=kconfig)
    kconfig.write_autoconf("generated/zephyr/autoconf.h")


def main() -> None:
    parser = argparse.ArgumentParser(description="Kconfig bazel port")

    parser.add_argument(
        "--kconfig",
        type=pathlib.Path,
        help="Root Kconfig file to load",
        required=True,
    )

    subparsers = parser.add_subparsers(
        dest="subcommand",
        required=True,
    )

    gen_kconfig_parser = subparsers.add_parser(
        "gen_kconfig",
        help="Generate generic kconfig BUILD",
    )
    gen_kconfig_parser.add_argument(
        "-o",
        type=pathlib.Path,
        help="Output file",
    )

    gen_project_parser = subparsers.add_parser(
        "gen_project",
        help="Generate BUILD file for a specific peroject",
    )
    gen_project_parser.add_argument(
        "--project",
        type=pathlib.Path,
        help="Project config file",
    )
    gen_project_parser.add_argument(
        "-o",
        type=pathlib.Path,
        help="Output file",
    )
    gen_project_parser.add_argument(
        "--extra_configs_in",
        type=pathlib.Path,
        nargs="*",
        help="Input configuration fragments. Will be merged together.",
    )

    args = parser.parse_args()

    kconfig_path = args.kconfig
    subcommand = args.subcommand

    if subcommand == "gen_kconfig":
        generate_kconfig_build_file(
            kconfig_path=kconfig_path,
            out=args.o,
        )
    elif subcommand == "gen_project":
        generate_project_build_file(
            kconfig_path=kconfig_path,
            project_path=args.project,
            extra_conf_files=args.extra_configs_in,
            out=args.o,
        )
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
