#! /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[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
