#!/usr/bin/python3 -s

import subprocess
from asciitree import LeftAligned
from collections import OrderedDict as OD

def get_reqs(reqs, tree, pkg):
    if pkg=='' or pkg in reqs:
        return
    print 'find reqs for', pkg
    proc = subprocess.Popen(['pip', 'show', pkg], stdout=subprocess.PIPE)
    out = proc.communicate()[0]
    try:
        pkg_ver = [r.split(':')[1].strip() for r in out.split('\n') if 'Version' in r][0]
        print "Version:", pkg_ver
        pkg_reqs = [[p.strip() for p in r.split(':')[1].split(',') if p.strip()!=""] for r in out.split('\n') if 'Requires' in r][0]
        reqs[pkg] = (pkg_ver, pkg_reqs)
        tree[pkg+'=='+pkg_ver] = OD()
        if len(pkg_reqs)==0:
           return
        map(lambda pkg_req: get_reqs(reqs, tree[pkg+'=='+pkg_ver], pkg_req), pkg_reqs)
    except IndexError:
        pass

def make_full_tree(reqs, pkg):
    t = OD()
    t[pkg+'=='+reqs[pkg][0]] = OD()
    def recursv(deps, t):
        for dep in deps:
            v, d = reqs[dep]
            t[dep+'=='+v] = OD()
            if len(d)>0:
                recursv(d, t[dep+'=='+v])
    recursv(reqs[pkg][1], t[pkg+'=='+reqs[pkg][0]])
    return t

def parse_reqs(reqs, pkg):
    l = []
    deps = reqs[pkg][1]
    def recursv(deps):
        for dep in deps:
            v, d = reqs[dep]
            if len(d)>0:
                recursv(d)
            if dep+'=='+v not in set(l):
                l.append(dep+'=='+v)
    recursv(deps)
    l.append(pkg+'=='+reqs[pkg][0])
    return l

if __name__=='__main__':
    import sys
    import os
    import argparse

    parser = argparse.ArgumentParser(description='get full list of dependencies for installed pip packages')
    parser.add_argument('pkg', help='installed pip package')
    parser.add_argument('--write', help='write to requirements.txt file', action='store_true')

    args = parser.parse_args()

    reqs = {}
    tree = OD()

    get_reqs(reqs, tree, args.pkg)
    if len(reqs)==0:
        print 'Package ['+args.pkg+'] not installed!'
        sys.exit()
    full_tree = make_full_tree(reqs, args.pkg)
    reqs_list = parse_reqs(reqs, args.pkg)
    if args.write:
        with open('requirements.txt', 'w') as fd:
            [fd.write(l+'\n') for l in reqs_list]

    print 25*'*'
    print "full dependency tree"
    print 25*'*'
    tr1 = LeftAligned()
    print(tr1(full_tree))

    print 25*'*'
    print "ordered tree -- no duplicates"
    print 25*'*'
    tr2 = LeftAligned()
    print(tr2(tree))

    print 25*'*'
    print "copy to requirements.txt (or use '--write' option)"
    print 25*'*'
    for l in reqs_list: print l

    print 25*'*'
    print "download to local: pip wheel --wheel-dir=/path/to/wheels -r requirements.txt"
    print "install from local: pip install --no-index --find-links=/path/to/wheels -r requirements.txt"
    print "install from online: pip install -r requirements.txt"
    print 25*'*'
