#! /usr/bin/env python

import argparse
import itertools
import os
import re
import sys
from collections import defaultdict

from use_lldb_suite import lldb_root

parser = argparse.ArgumentParser(
    description='Analyze LLDB project #include dependencies.')
parser.add_argument('--show-counts', default=False, action='store_true', 
    help='When true, show the number of dependencies from each subproject')
parser.add_argument('--discover-cycles', default=False, action='store_true',
    help='When true, find and display all project dependency cycles.  Note,'
         'this option is very slow')

args = parser.parse_args()

src_dir = os.path.join(lldb_root, "source")
inc_dir = os.path.join(lldb_root, "include")

src_map = {}

include_regex = re.compile('#include \"((lldb|Plugins|clang)(.*/)+).*\"')

def is_sublist(small, big):
    it = iter(big)
    return all(c in it for c in small)

def normalize_host(str):
    if str.startswith("lldb/Host"):
        return "lldb/Host"
    if str.startswith("Plugins"):
        return "lldb/" + str
    if str.startswith("lldb/../../source"):
        return str.replace("lldb/../../source", "lldb")
    return str

def scan_deps(this_dir, file):
    global src_map
    deps = {}
    this_dir = normalize_host(this_dir)
    if this_dir in src_map:
        deps = src_map[this_dir]

    with open(file) as f:
        for line in list(f):
            m = include_regex.match(line)
            if m is None:
                continue
            relative = m.groups()[0].rstrip("/")
            if relative == this_dir:
                continue
            relative = normalize_host(relative)
            if relative in deps:
                deps[relative] += 1
            elif relative != this_dir:
                deps[relative] = 1
    if this_dir not in src_map and len(deps) > 0:
        src_map[this_dir] = deps

for (base, dirs, files) in os.walk(inc_dir):
    dir = os.path.basename(base)
    relative = os.path.relpath(base, inc_dir)
    inc_files = filter(lambda x : os.path.splitext(x)[1] in [".h"], files)
    relative = relative.replace("\\", "/")
    for inc in inc_files:
        inc_path = os.path.join(base, inc)
        scan_deps(relative, inc_path)

for (base, dirs, files) in os.walk(src_dir):
    dir = os.path.basename(base)
    relative = os.path.relpath(base, src_dir)
    src_files = filter(lambda x : os.path.splitext(x)[1] in [".cpp", ".h", ".mm"], files)
    norm_base_path = os.path.normpath(os.path.join("lldb", relative))
    norm_base_path = norm_base_path.replace("\\", "/")
    for src in src_files:
        src_path = os.path.join(base, src)
        scan_deps(norm_base_path, src_path)
    pass

def is_existing_cycle(path, cycles):
    # If we have a cycle like # A -> B -> C (with an implicit -> A at the end)
    # then we don't just want to check for an occurrence of A -> B -> C in the
    # list of known cycles, but every possible rotation of A -> B -> C.  For
    # example, if we previously encountered B -> C -> A (with an implicit -> B
    # at the end), then A -> B -> C is also a cycle.  This is an important
    # optimization which reduces the search space by multiple orders of
    # magnitude.
    for i in range(0,len(path)):
        if any(is_sublist(x, path) for x in cycles):
            return True
        path = [path[-1]] + path[0:-1]
    return False

def expand(path_queue, path_lengths, cycles, src_map):
    # We do a breadth first search, to make sure we visit all paths in order
    # of ascending length.  This is an important optimization to make sure that
    # short cycles are discovered first, which will allow us to discard longer
    # cycles which grow the search space exponentially the longer they get.
    while len(path_queue) > 0:
        cur_path = path_queue.pop(0)
        if is_existing_cycle(cur_path, cycles):
            continue

        next_len = path_lengths.pop(0) + 1
        last_component = cur_path[-1]

        for item in src_map[last_component]:
            if item.startswith("clang"):
                continue

            if item in cur_path:
                # This is a cycle.  Minimize it and then check if the result is
                # already in the list of cycles.  Insert it (or not) and then
                # exit.
                new_index = cur_path.index(item)
                cycle = cur_path[new_index:]
                if not is_existing_cycle(cycle, cycles):
                    cycles.append(cycle)
                continue

            path_lengths.append(next_len)
            path_queue.append(cur_path + [item])
    pass

cycles = []

path_queue = [[x] for x in iter(src_map)]
path_lens = [1] * len(path_queue)

items = list(src_map.items())
items.sort(key = lambda A : A[0])

for (path, deps) in items:
    print(path + ":")
    sorted_deps = list(deps.items())
    if args.show_counts:
        sorted_deps.sort(key = lambda A: (A[1], A[0]))
        for dep in sorted_deps:
            print("\t{} [{}]".format(dep[0], dep[1]))
    else:
        sorted_deps.sort(key = lambda A: A[0])
        for dep in sorted_deps:
            print("\t{}".format(dep[0]))

def iter_cycles(cycles):
    global src_map
    for cycle in cycles:
        cycle.append(cycle[0])
        zipper = list(zip(cycle[0:-1], cycle[1:]))
        result = [(x, src_map[x][y], y) for (x,y) in zipper]
        total = 0
        smallest = result[0][1]
        for (first, value, last) in result:
            total += value
            smallest = min(smallest, value)
        yield (total, smallest, result)

if args.discover_cycles:
    print("Analyzing cycles...")

    expand(path_queue, path_lens, cycles, src_map)

    average = sum([len(x)+1 for x in cycles]) / len(cycles)

    print("Found {} cycles.  Average cycle length = {}.".format(len(cycles), average))
    counted = list(iter_cycles(cycles))
    if args.show_counts:
        counted.sort(key = lambda A: A[0])
        for (total, smallest, cycle) in counted:
            sys.stdout.write("{} deps to break: ".format(total))
            sys.stdout.write(cycle[0][0])
            for (first, count, last) in cycle:
                sys.stdout.write(" [{}->] {}".format(count, last))
            sys.stdout.write("\n")
    else:
        for cycle in cycles:
            cycle.append(cycle[0])
            print(" -> ".join(cycle))

    print("Analyzing islands...")
    islands = []
    outgoing_counts = defaultdict(int)
    incoming_counts = defaultdict(int)
    for (total, smallest, cycle) in counted:
        for (first, count, last) in cycle:
            outgoing_counts[first] += count
            incoming_counts[last] += count
    for cycle in cycles:
        this_cycle = set(cycle)
        disjoints = [x for x in islands if this_cycle.isdisjoint(x)]
        overlaps = [x for x in islands if not this_cycle.isdisjoint(x)]
        islands = disjoints + [set.union(this_cycle, *overlaps)]
    print("Found {} disjoint cycle islands...".format(len(islands)))
    for island in islands:
        print("Island ({} elements)".format(len(island)))
        sorted = []
        for node in island:
            sorted.append((node, incoming_counts[node], outgoing_counts[node]))
        sorted.sort(key = lambda x: x[1]+x[2])
        for (node, inc, outg) in sorted:
            print("  {} [{} in, {} out]".format(node, inc, outg))
    sys.stdout.flush()
pass
