#!/usr/bin/env python3
import argparse
import os
import sys

def resolve_includes(bundle_name, bundle_path, bundles=False):
    """
    resolve_incudes returns a full package list of include-resolved packages in
    the bundle definition file or pundle declaration under bundle_path. Sources
    for included bundles are other bundle definition files at
    bundle_path/bundles/* and bundle_path/packages.
    """
    bundle_def = os.path.join(bundle_path, "bundles", bundle_name)
    try:
        with open(bundle_def, "r", encoding="latin-1") as bundlef:
            lines = bundlef.readlines()
    except FileNotFoundError:
        # maybe this is a pundle
        packages_f = os.path.join(bundle_path, "packages")
        if not os.path.exists(packages_f):
            # pundle definition file does not exist
            print(f"ERROR: could not find {bundle_name} bundle")
            return set(), False

        # find name on its own line
        with open(packages_f, "r") as pkgdef:
            for line in pkgdef.readlines():
                # ignore things after a comment '#'
                c = line.find('#')
                if c >= 0:
                    line = line[:c]
                line = line.strip()
                if f"{bundle_name}" == line:
                    return set([bundle_name]), True

        print(f"ERROR: could not find {bundle_name} bundle")
        return set(), False

    packages = set()
    if bundles:
        packages.add(bundle_name)

    for line in lines:
        line = line.split("#", 1)[0].strip()
        if not line:
            continue

        if line.startswith("include("):
            inc_bundle = line[len("include("):].rsplit(")")[0]
            try:
                n_packages, success = resolve_includes(inc_bundle, bundle_path, bundles)
                if not success:
                    return set(), False
                packages = packages.union(n_packages)
            except RecursionError:
                print("ERROR: include loop found")
                return set(), False
            if bundles:
                packages.add(inc_bundle)

            continue

        if not bundles:
            packages.add(line)

    return packages, True

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Process bundle packages following includes')
    parser.add_argument('bundle_name', help='name of bundle to process')
    parser.add_argument('bundle_path', help='path to clr-bundles directory')
    parser.add_argument('--bundles', default=False, action='store_true',
                        help='Report only included bundle names')
    args = parser.parse_args()
    success = True
    if args.bundles:
        os_core_set = set(["os-core"])
    else:
        os_core_set, success = resolve_includes("os-core", args.bundle_path)

    if not success:
        sys.exit(1)

    bundle_set, success = resolve_includes(args.bundle_name, args.bundle_path, bundles=args.bundles)
    if not success:
        sys.exit(1)

    print('\n'.join(sorted(os_core_set.union(bundle_set))))
