#!/usr/bin/env python3
#
# Copyright (C) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: GPL-2.0-only
#

import os
import sys
import argparse
import logging
import re

class Dot(object):
    def __init__(self):
        parser = argparse.ArgumentParser(
            description="Analyse recipe-depends.dot generated by bitbake -g",
            formatter_class=argparse.RawDescriptionHelpFormatter)
        parser.add_argument("dotfile",
            help = "Specify the dotfile", nargs = 1, action='store', default='')
        parser.add_argument("-k", "--key",
            help = "Specify the key, e.g., recipe name",
            action="store", default='')
        parser.add_argument("-d", "--depends",
            help = "Print the key's dependencies",
            action="store_true", default=False)
        parser.add_argument("-w", "--why",
            help = "Print why the key is built",
            action="store_true", default=False)
        parser.add_argument("-r", "--remove",
            help = "Remove duplicated dependencies to reduce the size of the dot files."
                    " For example, A->B, B->C, A->C, then A->C can be removed.",
            action="store_true", default=False)

        parser.epilog = """
Examples:
First generate the .dot file:
    bitbake -g core-image-minimal

To find out why a package is being built:
    %(prog)s -k <package> -w ./task-depends.dot

To find out what a package depends on:
    %(prog)s -k <package> -d ./task-depends.dot

Reduce the .dot file packages only, no tasks:
    %(prog)s -r ./task-depends.dot
"""

        self.args = parser.parse_args()

        if len(sys.argv) != 3 and len(sys.argv) < 5:
            print('ERROR: Not enough args, see --help for usage')

    @staticmethod
    def insert_dep_chain(chain, rdeps, alldeps):
        """
        insert elements to chain from rdeps, according to alldeps
        """
        # chain should at least contain one element
        if len(chain) == 0:
            raise

        inserted_elements = []
        for rdep in rdeps:
            if rdep in chain:
                continue
            else:
                for i in range(0, len(chain)-1):
                    if chain[i] in alldeps[rdep] and rdep in alldeps[chain[i+1]]:
                        chain.insert(i+1, rdep)
                        inserted_elements.append(rdep)
                        break
                if chain[-1] in alldeps[rdep] and rdep not in chain:
                    chain.append(rdep)
                    inserted_elements.append(rdep)
        return inserted_elements

    @staticmethod
    def print_dep_chains(key, rdeps, alldeps):
        rlist = rdeps.copy()
        chain = []
        removed_rdeps = [] # hold rdeps removed from rlist

        chain.append(key)
        while (len(rlist) != 0):
            # insert chain from rlist
            inserted_elements = Dot.insert_dep_chain(chain, rlist, alldeps)
            if not inserted_elements:
                if chain[-1] in rlist:
                    rlist.remove(chain[-1])
                    removed_rdeps.append(chain[-1])
                chain.pop()
                continue
            else:
                # insert chain from removed_rdeps
                Dot.insert_dep_chain(chain, removed_rdeps, alldeps)
                print(' -> '.join(list(reversed(chain))))

    def main(self):
        #print(self.args.dotfile[0])
        # The format is {key: depends}
        depends = {}
        with open(self.args.dotfile[0], 'r') as f:
            for line in f.readlines():
                if ' -> ' not in line:
                    continue
                line_no_quotes = line.replace('"', '')
                m = re.match("(.*) -> (.*)", line_no_quotes)
                if not m:
                    print('WARNING: Found unexpected line: %s' % line)
                    continue
                key = m.group(1)
                if key == "meta-world-pkgdata":
                    continue
                dep = m.group(2)
                key = key.split('.')[0]
                dep = dep.split('.')[0]
                if key == dep:
                    continue
                if key in depends:
                    if not key in depends[key]:
                        depends[key].add(dep)
                    else:
                        print('WARNING: Fonud duplicated line: %s' % line)
                else:
                    depends[key] = set()
                    depends[key].add(dep)

        if self.args.remove:
            reduced_depends = {}
            for k, deps in depends.items():
                child_deps = set()
                added = set()
                # Both direct and indirect depends are already in the dict, so
                # we don't have to do this recursively.
                for dep in deps:
                    if dep in depends:
                        child_deps |= depends[dep]

                reduced_depends[k] = deps - child_deps
                outfile= '%s-reduced%s' % (self.args.dotfile[0][:-4], self.args.dotfile[0][-4:])
            with open(outfile, 'w') as f:
                print('Saving reduced dot file to %s' % outfile)
                f.write('digraph depends {\n')
                for k, v in reduced_depends.items():
                    for dep in v:
                        f.write('"%s" -> "%s"\n' % (k, dep))
                f.write('}\n')
            sys.exit(0)

        if self.args.key not in depends:
            print("ERROR: Can't find key %s in %s" % (self.args.key, self.args.dotfile[0]))
            sys.exit(1)

        if self.args.depends:
            if self.args.key in depends:
                print('Depends: %s' % ' '.join(depends[self.args.key]))

        reverse_deps = []
        if self.args.why:
            for k, v in depends.items():
                if self.args.key in v and not k in reverse_deps:
                    reverse_deps.append(k)
            print('Because: %s' % ' '.join(reverse_deps))
            Dot.print_dep_chains(self.args.key, reverse_deps, depends)

if __name__ == "__main__":
    try:
        dot = Dot()
        ret = dot.main()
    except Exception as esc:
        ret = 1
        import traceback
        traceback.print_exc()
    sys.exit(ret)
