# 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.
"""Common utilities for converting CMakeLists.txt to BUILD.bazel."""

from pathlib import Path
import re
from typing import Any, Callable


def translate_relative_path(
    absolute_path: Path, start_dir: Path, target_dir: Path
) -> Path:
    """Translates an absolute_path to a target directory.

    For example, start_dir / some / file -> target_dir / some / file.
    """
    if not absolute_path.is_relative_to(start_dir):
        raise ValueError(f'{absolute_path} is not inside {start_dir}')

    relative_path = absolute_path.relative_to(start_dir)
    return target_dir / relative_path


def process_if_block_start(line: str) -> dict[str, Any]:
    """Processes the start of a CMake if block."""
    condition = re.match(r'^if\s*\((.*)\)', line).group(1).strip()
    if_block = {
        'type': 'if_block',
        'branches': [{'condition': condition, 'body': []}],
        'else_body': None,
    }
    return if_block


def process_if_block_branch(line: str) -> dict[str, Any]:
    """Processes a CMake elseif branch."""
    condition = re.match(r'^elseif\s*\((.*)\)', line).group(1).strip()
    if_block_branch = {'condition': condition, 'body': []}
    return if_block_branch


def merge_bracketed_string(input_text: str) -> str:
    """Merges a CMake statement spanning multiple lines into one line."""
    lines = input_text.splitlines()
    output_lines = []
    buffer = ''
    inside_bracket = False

    for line in lines:
        comment_start_index = line.find('#')

        if comment_start_index != -1:
            line = line[:comment_start_index]

        stripped_line = line.strip()

        if not buffer:
            buffer = stripped_line
        else:
            if inside_bracket:
                if buffer.endswith('(') or stripped_line.startswith(')'):
                    buffer += stripped_line
                else:
                    buffer += ' ' + stripped_line
            else:
                output_lines.append(buffer)
                buffer = stripped_line

        if '(' in line:
            inside_bracket = True
        if ')' in line:
            inside_bracket = False

    if buffer:
        output_lines.append(buffer)

    return '\n'.join(output_lines)


def _process_zephyr_cmake_functions(
    line: str,
) -> dict[str, str | list[str]] | None:
    if line.startswith('zephyr_library_sources('):
        srcs = (
            re.search(r'zephyr_library_sources\((.*)\)', line).group(1).strip()
        )
        if srcs == 'uart_native_pty.c':
            srcs += ' uart_native_pty_bottom.c'
        if srcs == 'uart_native_tty.c':
            srcs += ' uart_native_tty_bottom.c'
        return {'type': 'unconditional_source', 'srcs': srcs.split()}
    elif line.startswith('zephyr_library_sources_ifdef('):
        config, srcs = re.search(
            r'zephyr_library_sources_ifdef\((\S+)\s+(.*)\)', line
        ).groups()
        if srcs == 'uart_native_pty.c':
            srcs += ' uart_native_pty_bottom.c'
        if srcs == 'uart_native_tty.c':
            srcs += ' uart_native_tty_bottom.c'
        return {
            'type': 'conditional_source',
            'config': config.strip(),
            'srcs': srcs.strip().split(),
        }
    elif line.startswith('zephyr_library_sources_ifndef('):
        config, srcs = re.search(
            r'zephyr_library_sources_ifndef\((\S+)\s+(.*)\)', line
        ).groups()
        return {
            'type': 'conditional_source_inverse',
            'config': config.strip(),
            'srcs': srcs.strip().split(),
        }
    elif line.startswith('zephyr_sources('):
        srcs = re.search(r'zephyr_sources\((.*)\)', line).group(1).strip()
        return {'type': 'unconditional_source', 'srcs': srcs.split()}
    elif line.startswith('zephyr_sources_ifdef('):
        config, srcs = re.search(
            r'zephyr_sources_ifdef\((\S+)\s+(.*)\)', line
        ).groups()
        return {
            'type': 'conditional_source',
            'config': config.strip(),
            'srcs': srcs.strip().split(),
        }
    elif line.startswith('zephyr_sources_ifndef('):
        config, srcs = re.search(
            r'zephyr_sources_ifndef\((\S+)\s+(.*)\)', line
        ).groups()
        return {
            'type': 'conditional_source_inverse',
            'config': config.strip(),
            'srcs': srcs.strip().split(),
        }
    elif line.startswith('zephyr_syscall_header('):
        syscall_client_files = (
            re.search(r'zephyr_syscall_header\((.*)\)', line).group(1).strip()
        )
        return {
            'type': 'unconditional_syscall_client_files',
            'files': syscall_client_files.split(),
        }
    elif line.startswith('zephyr_syscall_header_ifdef('):
        config, syscall_client_files = re.search(
            r'zephyr_syscall_header_ifdef\((\S+)\s+(.*)\)', line
        ).groups()
        return {
            'type': 'conditional_syscall_client_files',
            'config': config.strip(),
            'files': syscall_client_files.strip().split(),
        }
    elif line.startswith('add_subdirectory('):
        subdir_name = re.search(r'add_subdirectory\((\S+)\)', line).group(1)
        return {
            'type': 'unconditional_subdir',
            'subdir_name': subdir_name,
        }
    elif line.startswith('add_subdirectory_ifdef('):
        config, subdir_name = re.search(
            r'add_subdirectory_ifdef\((\S+)\s+(\S+)\)', line
        ).groups()
        if subdir_name.startswith('./'):
            subdir_name = subdir_name.removeprefix('./')
        return {
            'type': 'conditional_subdir',
            'config': config,
            'subdir_name': subdir_name,
        }
    elif line.startswith('zephyr_linker_sources('):
        # zephyr_linker_sources() supports two usages:
        # 1. zephyr_linker_sources(<location> <files>)
        # 2. zephyr_linker_sources(<location> SORT_KEY <key> <files>)
        #
        # Regex breakdown:
        # 1. zephyr_linker_sources\(\s* -> Match function name and opening paren
        # 2. (?P<location>\S+)           -> Capture first arg (location)
        # 3. \s+                         -> Require whitespace separator
        # 4. (?:SORT_KEY\s+(?P<key>\S+)\s+)? -> Optional group: Literal "SORT_KEY", space, capture <key>, space
        # 5. (?P<files>.+?)              -> Capture a list of files
        # 6. \s*\)                       -> Match trailing whitespace and closing paren
        pattern = (
            r'zephyr_linker_sources\(\s*'
            r'(?P<location>\S+)\s+'  # Capture location
            r'(?:SORT_KEY\s+(?P<key>\S+)\s+)?'  # Optional SORT_KEY group
            r'(?P<files>.+?)\s*\)'  # Capture files list
        )

        match = re.search(pattern, line)
        if match:
            location = match.group('location')
            files_list = match.group('files').split()
            # If 'key' was not found in the optional group, default it to 'default'
            sort_key = match.group('key') if match.group('key') else 'default'
            return {
                'type': 'linker_fragment',
                'location': location,
                'sort_key': sort_key,
                'files': files_list,
            }
        print(f'Failed to parse "{line}", skipping...')
        return None
    elif line.startswith('zephyr_linker_sources_ifdef('):
        # zephyr_linker_sources_ifdef() supports two usages:
        # 1. zephyr_linker_sources_ifdef(<condition> <location> <files>)
        # 2. zephyr_linker_sources_ifdef(<condition> <location> SORT_KEY <key> <files>)
        pattern = (
            r'zephyr_linker_sources_ifdef\(\s*'
            r'(?P<condition>\S+)\s+'  # Capture condition
            r'(?P<location>\S+)\s+'  # Capture location
            r'(?:SORT_KEY\s+(?P<key>\S+)\s+)?'  # Optional SORT_KEY group
            r'(?P<files>.+?)\s*\)'  # Capture files list
        )

        match = re.search(pattern, line)
        if match:
            return {
                'type': 'conditional_linker_fragment',
                'condition': match.group('condition'),
                'location': match.group('location'),
                # Default to "default" if key is missing
                'sort_key': (
                    match.group('key') if match.group('key') else 'default'
                ),
                'files': match.group('files').split(),
            }
        print(f'Failed to parse "{line}", skipping...')
        return None
    else:
        return None


def build_ast(
    lines: list[str],
) -> list[dict[str, Any]]:
    """Builds an Abstract Syntax Tree from CMakeLists.txt lines."""
    ast = []
    stack = [ast]

    for line in lines:
        line = line.strip()

        if re.match(r'^if\s*\(', line):
            if_block = process_if_block_start(line)
            stack[-1].append(if_block)
            stack.append(if_block)
            stack.append(if_block['branches'][0]['body'])
            continue

        elif re.match(r'^elseif\s*\(', line):
            stack.pop()
            if_block = stack[-1]
            if if_block['type'] != 'if_block':
                raise ValueError('elseif without a preceding if')
            if_block_branch = process_if_block_branch(line)
            if_block['branches'].append(if_block_branch)
            stack.append(if_block_branch['body'])
            continue

        elif re.match(r'^else\s*\(', line):
            stack.pop()
            if_block = stack[-1]
            if if_block['type'] != 'if_block':
                raise ValueError('else without a preceding if')
            if_block['else_body'] = []
            stack.append(if_block['else_body'])
            continue

        elif re.match(r'^endif\s*\(', line):
            stack.pop()
            if stack and stack[-1]['type'] == 'if_block':
                stack.pop()
            continue

        source_file_item = _process_zephyr_cmake_functions(line)
        if source_file_item:
            node_body = stack[-1]
            node_body.append(source_file_item)

    return ast


# Int type Kconfig symbols that we should take care of in converting
# CMakeLists.txt. An ifdef() on these symbols means the source is added only if
# the int flag value is nonzero.
_INT_CONFIGS_TO_PROCESS = [
    'CONFIG_SYS_HEAP_ARRAY_SIZE',
]


def _get_unique_target_name(
    start_name: str, names_list: list[str]
) -> tuple[str, str]:
    """Generates a unique target name not already in names_list."""
    target_name = start_name + '.target'
    target_name_bazel_str = f'":{target_name}"'
    while target_name_bazel_str in names_list:
        # Name collision. Modify the target name.
        target_name += '#'
        target_name_bazel_str = f'":{target_name}"'
    return target_name, target_name_bazel_str


def traverse_ast(
    ast: list[dict[str, Any]],
    target_name: str,
    update_rules_fn: Callable[[list[str], ...], list[str]],
    is_root=False,
    # Ignore linker fragments by default.
    ignore_node_types=['linker_fragment', 'conditional_linker_fragment'],
) -> list[str]:
    """Recursively generates Bazel rules from the AST."""
    rules = []
    unconditional_srcs = []
    toplevel_conditional_srcs = []
    unconditional_deps = []
    deps_selects = []

    # Process all nodes at the current level
    for node in ast:
        if node['type'] in ignore_node_types:
            continue

        if node['type'] == 'unconditional_source':
            for src in node['srcs']:
                unconditional_srcs.append(f'        "{src}",')
        elif node['type'] == 'conditional_source':
            if node['config'] in _INT_CONFIGS_TO_PROCESS:
                # For int symbols in the conditional case, add source if the
                # value is NON-ZERO.
                toplevel_conditional_srcs.append(
                    '\n'.join([
                        ' + select({',
                        f'        "@zephyr_kconfig//:{node["config"]}=0": [],',
                        '        "//conditions:default": [',
                        *[f'            "{src}",' for src in node['srcs']],
                        '        ],',
                        '    })',
                    ])
                )
            else:
                toplevel_conditional_srcs.append(
                    '\n'.join([
                        ' + select({',
                        '        "//conditions:default": [],',
                        f'        "@zephyr_kconfig//:{node["config"]}=true": [',
                        *[f'            "{src}",' for src in node['srcs']],
                        '        ],',
                        '    })',
                    ])
                )
        elif node['type'] == 'conditional_source_inverse':
            toplevel_conditional_srcs.append(
                '\n'.join([
                    ' + select({',
                    f'        "@zephyr_kconfig//:{node["config"]}=true": [],',
                    '        "//conditions:default": [',
                    *[f'            "{src}",' for src in node['srcs']],
                    '        ],',
                    '    })',
                ])
            )
        elif node['type'] == 'unconditional_subdir':
            unconditional_deps.append(
                f'"//" + package_name() + "/{node["subdir_name"]}"'
            )
        elif node['type'] == 'conditional_subdir':
            conditional_subdir_target_name = (
                f'"//" + package_name() + "/{node["subdir_name"]}"'
            )
            select_str = '\n'.join([
                ' + select({',
                f'        "@zephyr_kconfig//:{node["config"]}=true": [',
                f'            {conditional_subdir_target_name},',
                '        ],',
                '        "//conditions:default": [],',
                '    })',
            ])
            deps_selects.append(select_str)
        elif node['type'] == 'linker_fragment':
            # Use the linker file name as the base of the target name.
            local_target_name, local_target_name_bazel_str = (
                _get_unique_target_name(node['files'][0], unconditional_deps)
            )
            rules.append(f"""zephyr_linker_fragment(
    name = "{local_target_name}",
    srcs = {node['files']},
    location = "{node['location']}",
    sort_key = "{node['sort_key']}",
)
""")
            # Track this rule so that the umbrella linker fragment rule can
            # depend on it.
            unconditional_deps.append(local_target_name_bazel_str)
        elif node['type'] == 'conditional_linker_fragment':
            # Use the linker file name as the base of the target name.
            local_target_name, local_target_name_bazel_str = (
                _get_unique_target_name(node['files'][0], unconditional_deps)
            )
            rules.append(f"""zephyr_linker_fragment(
    name = "{local_target_name}",
    srcs = select({{
        "@zephyr_kconfig//:{node['condition']}=true": {node['files']},
        "//conditions:default": [],
    }}),
    location = "{node['location']}",
    sort_key = "{node['sort_key']}",
)
""")
            # Track this rule so that the umbrella linker fragment rule can
            # depend on it.
            unconditional_deps.append(local_target_name_bazel_str)
        elif node['type'] == 'if_block':
            if_block_rules, deps_select = parse_if_block_ast_node(
                node,
                target_name,
                lambda child, child_name: traverse_ast(
                    child,
                    child_name,
                    update_rules_fn,
                    ignore_node_types=ignore_node_types,
                ),
            )
            rules.extend(if_block_rules)
            if deps_select:
                deps_selects.append(deps_select)

    # Merge unconditional and top-level conditional sources.
    srcs_content = '[\n'
    for unconditional_src in unconditional_srcs:
        srcs_content += unconditional_src + '\n'
    srcs_content += '    ]'
    srcs_content += ''.join(toplevel_conditional_srcs)

    defines_content = ''
    if target_name in ('uart_native_pty', 'uart_native_tty'):
        defines_content = ',\n    defines = ["_POSIX_C_SOURCE=200809L"]'

    # AST node has been parsed.
    # Call the provided hook to update the Bazel rules.
    rules = update_rules_fn(
        rules,
        target_name,
        srcs_content + defines_content,
        unconditional_deps,
        deps_selects,
        is_root,
    )
    return rules


def _user_ack(prompt: str) -> bool:
    while True:
        response = input(f'{prompt} (y/n): ').lower()

        if response == 'y' or response == 'yes':
            return True
        elif response == 'n' or response == 'no':
            return False
        else:
            print("Invalid input. Please enter 'y' or 'n'")


def parse_if_block_ast_node(
    node: dict[str, Any], target_name: str, recursive_callback: Callable
) -> tuple[list[str], str]:
    rules = []
    select_dict_entries = []
    else_condition = '//conditions:default'

    # Process if/elseif branches
    for i, branch in enumerate(node['branches']):
        # Track compound condition rules created so that we can
        # backtrack.
        config_setting_rules_created = 0
        condition = branch['condition']
        branch_body = branch['body']
        sanitized_condition = re.sub(r'[^a-zA-Z0-9_]', '_', condition).lower()
        child_target_name = f'{target_name}_{sanitized_condition}_deps'

        compound_types = 0
        for compound_type in [' OR ', ' AND ']:
            if compound_type in condition:
                compound_types += 1
        if compound_types > 1:
            if _user_ack(
                f'Cannot handle complex compound condition {condition},'
                ' please confirm okay to skip'
            ):
                continue
            else:
                raise ValueError(
                    f'Cannot handle complex compound condition: {condition}'
                )

        if re.match(r'NOT\s+CONFIG_\S+', condition):
            # NOT CONFIG_XXX
            real_condition = re.search(r'^NOT\s+(\S+)', condition).group(1)
            # Invert else condition.
            else_condition = f'@zephyr_kconfig//:{real_condition}=true'
            select_dict_entries.append(
                f'        "//conditions:default": [":{child_target_name}"],'
            )
        elif re.match(r'\S+\s+OR\s+', condition):
            or_conditions = re.split(r'\s+OR\s+', condition)
            to_match = []
            for or_condition in or_conditions:
                if re.match(r'NOT\s+CONFIG_\S+', or_condition):
                    real_condition = re.search(
                        r'^NOT\s+(\S+)', or_condition
                    ).group(1)
                    # Define the inverse config_setting to use in match_any below.
                    inverse_condition_name = or_condition.replace(
                        ' ', '_'
                    ).lower()
                    rules.append(f"""config_setting(
    name = "{inverse_condition_name}",
    flag_values = {{
        "@zephyr_kconfig//:{real_condition}": "false",
    }},
)""")
                    to_match.append(f':{inverse_condition_name}')
                else:
                    to_match.append(f'@zephyr_kconfig//:{or_condition}=true')
            rules.append(f"""selects.config_setting_group(
    name = "{sanitized_condition}",
    match_any = {to_match},
)""")
            config_setting_rules_created += 1
            select_dict_entries.append(
                f'        ":{sanitized_condition}": [":{child_target_name}"],'
            )
        elif re.match(r'\S+\s+AND\s+', condition):
            and_conditions = re.split(r'\s+AND\s+', condition)
            to_match = []
            for and_condition in and_conditions:
                if re.match(r'NOT\s+CONFIG_\S+', and_condition):
                    real_condition = re.search(
                        r'^NOT\s+(\S+)', and_condition
                    ).group(1)
                    # Define the inverse config_setting to use in match_all below.
                    inverse_condition_name = and_condition.replace(
                        ' ', '_'
                    ).lower()
                    rules.append(f"""config_setting(
    name = "{inverse_condition_name}",
    flag_values = {{
        "@zephyr_kconfig//:{real_condition}": "false",
    }},
)""")
                    config_setting_rules_created += 1
                    to_match.append(f':{inverse_condition_name}')
                else:
                    to_match.append(f'@zephyr_kconfig//:{and_condition}=true')
            rules.append(f"""selects.config_setting_group(
    name = "{sanitized_condition}",
    match_all = {to_match},
)""")
            config_setting_rules_created += 1
            select_dict_entries.append(
                f'        ":{sanitized_condition}": [":{child_target_name}"],'
            )
        elif re.match(r'CONFIG_\S+', condition):
            # Regular CONFIG_XXX without AND, OR, NOT.
            select_dict_entries.append(
                f'        "@zephyr_kconfig//:{condition}=true":'
                f' [":{child_target_name}"],'
            )
        else:
            print(f'Cannot process condition {condition}, skipping...')
            continue

        # Recursively generate rules for the branch body
        child_rules = recursive_callback(branch_body, child_target_name)

        if child_rules:
            rules.extend(child_rules)
        else:
            # Child does not have any content, remove the empty select.
            select_dict_entries.pop()
            # Since the select is empty, compound condition rules are
            # useless too.
            for _ in range(config_setting_rules_created):
                rules.pop()

    # Process else branch
    if node['else_body'] is not None:
        child_target_name = f'{target_name}_else_deps'
        child_rules = recursive_callback(node['else_body'], child_target_name)
        if child_rules:
            rules.extend(child_rules)
            select_dict_entries.append(
                f'        "{else_condition}": [":{child_target_name}"],'
            )
    elif select_dict_entries:
        # Else condition is only meaningful if there exist other
        # conditions already.
        select_dict_entries.append(f'        "{else_condition}": [],')

    deps_select = ''
    if select_dict_entries:
        deps_select = '\n'.join([
            ' + select({',
            *select_dict_entries,
            '    })',
        ])

    return rules, deps_select
