#!/usr/bin/env fuchsia-vendored-python
#
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Generate fidl_project.json file declaring FIDL libraries.

This script reads the generated_sources.json file which contains the paths to
fidlc-generated JSON IR, and generates a fidl_project.json file which declares
all FIDL libraries along with their constituent files, dependencies, and build
artifacts (JSON IR and bindings). This is for use in the FIDL Language Server,
which uses fidl_project to do dependency resolution.
"""

import argparse
import json
import os
import re
from pathlib import Path

# fidl_project.json schema: list of Library
# where Library is
# {
#     "name": string,
#     "files": []string,
#     "json": string,
#     "deps": []string,
#     "bindings": {
#         "hlcpp": {},
#         "llcpp": {},
#         "rust": {},
#         "go": {},
#         "dart": {},
#         ...
#     }
# }

# https://fuchsia.dev/fuchsia-src/development/languages/fidl/reference/language.md#identifiers
identifier_pattern = r"[a-zA-Z](?:[a-zA-Z0-9_]*[a-zA-Z0-9])?"

# Although "library" can be used anywhere (e.g. as a type name), this regex
# is robust because the the library declaration must appear at the top of
# the file (only comments and whitespace can precede it).
library_pattern = (
    r"^(?:\s*//[^\n]*\n)*\s*"
    + r"library\s+("
    + identifier_pattern
    + r"(?:\."
    + identifier_pattern
    + r")*"
    + r")\s*;"
)


def find_files(
    library_name: str, library_json: str, *, fuchsia_dir: Path
) -> list[str]:
    pattern = r"^fidling\/gen\/([\w\.\/-]+)\/[\w\-. ]+\.fidl\.json$"
    result = re.search(pattern, library_json)
    if not result or not result.group(1):
        return []

    fidl_dir = fuchsia_dir / result.group(1)
    globs = [
        fidl_dir.glob("*.fidl"),
        fidl_dir.parent.glob("*.fidl"),
    ]

    files = []
    for glob in globs:
        for file in glob:
            # Read in FIDL file
            with open(file, "r") as f:
                # Parse `library` decl
                result = re.search(library_pattern, f.read())
                # Check that it matches library name
                if not result or not result.group(1):
                    continue
                if result.group(1) != library_name:
                    continue
            files.append(str(file))
    return files


def find_deps(library_json: str, *, root_build_dir: Path) -> list[str] | None:
    library_json_path = root_build_dir / library_json

    if not os.path.isfile(library_json_path):
        return None

    with open(library_json_path, "r") as f:
        library = json.load(f)
        deps = library["library_dependencies"]
        deps = [dep["name"] for dep in deps]
        return deps


def gen_fidl_project(
    *,
    root_build_dir: Path,
    fuchsia_dir: Path,
    generated_sources_path: Path,
    fidl_project_path: Path,
) -> None:
    result = []
    with open(generated_sources_path, "r") as f:
        artifacts = json.load(f)

    processed = set()
    for artifact in artifacts:
        if artifact in processed:
            continue

        if not artifact.endswith(".fidl.json"):
            continue

        deps = find_deps(artifact, root_build_dir=root_build_dir)
        if deps is None:
            continue

        # Get JSON filename out of artifact
        library_name = os.path.basename(artifact)
        # Remove .fidl.json suffix
        library_name = library_name[:-10]

        processed.add(artifact)
        result.append(
            {
                "name": library_name,
                # Path is not JSON serializable.
                "json": str(root_build_dir / artifact),
                "files": find_files(
                    library_name, artifact, fuchsia_dir=fuchsia_dir
                ),
                "deps": deps,
                "bindings": {},  # TODO
            }
        )

    with open(fidl_project_path, "w") as f:
        json.dump(result, f, indent=4, sort_keys=True)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Generate fidl_project.json file declaring FIDL libraries."
    )
    parser.add_argument("root_build_dir", type=Path)
    parser.add_argument("fuchsia_dir", type=Path)
    parser.add_argument("generated_sources_path", type=Path)
    parser.add_argument("fidl_project_path", type=Path)
    args = parser.parse_args()

    gen_fidl_project(
        root_build_dir=args.root_build_dir,
        fuchsia_dir=args.fuchsia_dir,
        generated_sources_path=args.generated_sources_path,
        fidl_project_path=args.fidl_project_path,
    )
