#!/bin/env python3

# SPDX-FileCopyrightText: 2023 Debian Rust Maintainers
# SPDX-License-Identifier: MIT

import toml
import os
import sys

from typing import Dict, List, Any


def flatten_features(feature: str, pool: Dict[str, List[str]]) -> List[str]:
    my_features = pool.get(feature)
    flattened = []
    if my_features is None:
        return [feature]
    for f in my_features:
        child_feature = pool.get(f)
        if child_feature is None:
            flattened.append(f)
            # a crate dependency, not a feature
            continue
        flattened.extend(flatten_features(f, pool))
    return flattened


def load_toml(path: str) -> Dict[str, Any]:
    with open(path, "r") as f:
        return toml.load(f)


def flatten_local_crates(path: str) -> str:
    toml_data = load_toml(os.path.join(path, "Cargo.toml"))
    local_crates = {}
    for k, v in toml_data["dependencies"].items():
        if "path" in v:
            crate_path = os.path.join(path, v["path"], "Cargo.toml")
            local_crates[k] = load_toml(crate_path)
    ws_crates = toml_data["dependencies"].keys()
    # scan features for references to local crates
    for k, v in toml_data["features"].items():
        for feature in v:
            if "/" not in feature:
                continue
            crate, feature_name = feature.split("/", 1)
            if crate not in local_crates:
                continue
            # replace the references with concrete features
            flattened = flatten_features(
                feature_name, local_crates[crate]["features"])
            for i in flattened:
                if i in ws_crates:
                    flattened.remove(i)
            toml_data["features"][k] = flattened
    # merge local crate dependencies with workspace dependencies
    for crate in local_crates.values():
        for k, v in crate["dependencies"].items():
            if k in ws_crates:
                continue
            toml_data["dependencies"][k] = v
    # remove local crates that in the workspace
    for local_crate in local_crates.keys():
        del toml_data["dependencies"][local_crate]

    return toml.dumps(toml_data)


if __name__ == "__main__":
    if len(sys.argv) not in (2, 3):
        print(f"Usage: python3 {sys.argv[0]} <path/to/crate/root> [output/Cargo.toml]")
        exit(1)
    modified = flatten_local_crates(sys.argv[1])
    modified_file = sys.argv[2] if len(sys.argv) == 3 else os.path.join(sys.argv[1], "Cargo.toml")
    with open(modified_file, "w") as f:
        f.write(modified)
