#!/usr/bin/env python
#===----------------------------------------------------------------------===##
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===----------------------------------------------------------------------===##

import argparse
import os
import re


def is_config_header(h):
    return os.path.basename(h) in ['__config', '__libcpp_version']


def is_experimental_header(h):
    return ('experimental/' in h) or ('ext/' in h)


def is_support_header(h):
    return '__support/' in h


class FileEntry:
    def __init__(self, includes, individual_linecount):
        self.includes = includes
        self.individual_linecount = individual_linecount
        self.cumulative_linecount = None  # documentation: this gets filled in later
        self.is_graph_root = None  # documentation: this gets filled in later


def list_all_roots_under(root):
    result = []
    for root, _, files in os.walk(root):
        for fname in files:
            if '__support' in root:
                pass
            elif ('.' in fname and not fname.endswith('.h')):
                pass
            else:
                result.append(root + '/' + fname)
    return result


def build_file_entry(fname, options):
    assert os.path.exists(fname)

    def locate_header_file(h, paths):
        for p in paths:
            fullname = p + '/' + h
            if os.path.exists(fullname):
                return fullname
        if options.error_on_file_not_found:
            raise RuntimeError('Header not found: %s, included by %s' % (h, fname))
        return None

    local_includes = []
    system_includes = []
    linecount = 0
    with open(fname, 'r') as f:
        for line in f.readlines():
            linecount += 1
            m = re.match(r'\s*#\s*include\s+"([^"]*)"', line)
            if m is not None:
                local_includes.append(m.group(1))
            m = re.match(r'\s*#\s*include\s+<([^>]*)>', line)
            if m is not None:
                system_includes.append(m.group(1))

    fully_qualified_includes = [
        locate_header_file(h, options.search_dirs)
        for h in system_includes
    ] + [
        locate_header_file(h, os.path.dirname(fname))
        for h in local_includes
    ]

    return FileEntry(
        # If file-not-found wasn't an error, then skip non-found files
        includes = [h for h in fully_qualified_includes if h is not None],
        individual_linecount = linecount,
    )


def transitive_closure_of_includes(graph, h1):
    visited = set()
    def explore(graph, h1):
        if h1 not in visited:
            visited.add(h1)
            for h2 in graph[h1].includes:
                explore(graph, h2)
    explore(graph, h1)
    return visited


def transitively_includes(graph, h1, h2):
    return (h1 != h2) and (h2 in transitive_closure_of_includes(graph, h1))


def build_graph(roots, options):
    original_roots = list(roots)
    graph = {}
    while roots:
        frontier = roots
        roots = []
        for fname in frontier:
            if fname not in graph:
                graph[fname] = build_file_entry(fname, options)
                graph[fname].is_graph_root = (fname in original_roots)
                roots += graph[fname].includes
    for fname, entry in graph.items():
        entry.cumulative_linecount = sum(graph[h].individual_linecount for h in transitive_closure_of_includes(graph, fname))
    return graph


def get_graphviz(graph, options):

    def get_friendly_id(fname):
        i = fname.index('include/')
        assert(i >= 0)
        result = fname[i+8:]
        return result

    def get_decorators(fname, entry):
        result = ''
        if entry.is_graph_root:
            result += ' [style=bold]'
        if options.show_individual_line_counts and options.show_cumulative_line_counts:
            result += ' [label="%s\\n%d indiv, %d cumul"]' % (
                get_friendly_id(fname), entry.individual_linecount, entry.cumulative_linecount
            )
        elif options.show_individual_line_counts:
            result += ' [label="%s\\n%d indiv"]' % (get_friendly_id(fname), entry.individual_linecount)
        elif options.show_cumulative_line_counts:
            result += ' [label="%s\\n%d cumul"]' % (get_friendly_id(fname), entry.cumulative_linecount)
        return result

    result = ''
    result += 'strict digraph {\n'
    result += '    rankdir=LR;\n'
    result += '    layout=dot;\n\n'
    for fname, entry in graph.items():
        result += '    "%s"%s;\n' % (get_friendly_id(fname), get_decorators(fname, entry))
        for h in entry.includes:
            if any(transitively_includes(graph, i, h) for i in entry.includes) and not options.show_transitive_edges:
                continue
            result += '        "%s" -> "%s";\n' % (get_friendly_id(fname), get_friendly_id(h))
    result += '}\n'
    return result


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Produce a dependency graph of libc++ headers, in GraphViz dot format.')
    parser.add_argument('--root', default=None, metavar='FILE', help='File or directory to be the root of the dependency graph')
    parser.add_argument('-I', dest='search_dirs', default=[], action='append', metavar='DIR', help='Path(s) to search for local includes')
    parser.add_argument('--show-transitive-edges', action='store_true', help='Show edges to headers that are transitively included anyway')
    parser.add_argument('--show-config-headers', action='store_true', help='Show headers named __config')
    parser.add_argument('--show-experimental-headers', action='store_true', help='Show headers in the experimental/ and ext/ directories')
    parser.add_argument('--show-support-headers', action='store_true', help='Show headers in the __support/ directory')
    parser.add_argument('--show-individual-line-counts', action='store_true', help='Include an individual line count in each node')
    parser.add_argument('--show-cumulative-line-counts', action='store_true', help='Include a total line count in each node')
    parser.add_argument('--error-on-file-not-found', action='store_true', help="Don't ignore failure to open an #included file")

    options = parser.parse_args()

    if options.root is None:
        curr_dir = os.path.dirname(os.path.abspath(__file__))
        options.root = os.path.join(curr_dir, '../include')

    if options.search_dirs == [] and os.path.isdir(options.root):
        options.search_dirs = [options.root]

    options.root = os.path.abspath(options.root)
    options.search_dirs = [os.path.abspath(p) for p in options.search_dirs]

    if os.path.isdir(options.root):
        roots = list_all_roots_under(options.root)
    elif os.path.isfile(options.root):
        roots = [options.root]
    else:
        raise RuntimeError('--root seems to be invalid')

    graph = build_graph(roots, options)

    # Eliminate certain kinds of "visual noise" headers, if asked for.
    def should_keep(fname):
        return all([
            options.show_config_headers or not is_config_header(fname),
            options.show_experimental_headers or not is_experimental_header(fname),
            options.show_support_headers or not is_support_header(fname),
        ])

    for fname in list(graph.keys()):
        if should_keep(fname):
            graph[fname].includes = [h for h in graph[fname].includes if should_keep(h)]
        else:
            del graph[fname]

    # Look for cycles.
    no_cycles_detected = True
    for fname, entry in graph.items():
        for h in entry.includes:
            if transitively_includes(graph, h, fname):
                print('Cycle detected between %s and %s' % (fname, h))
                no_cycles_detected = False
    assert no_cycles_detected

    print(get_graphviz(graph, options))
