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