#! /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 = [x for x in files if os.path.splitext(x)[1] in [".h"]]
    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 = [x for x in files if os.path.splitext(x)[1] in [".cpp", ".h", ".mm"]]
    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.get(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
