#!/usr/bin/env python
# coding: utf-8
# pylint: disable=F0401,C0111,W0232,E1101,E1103,C0301

#  Copyright 2015 by Leipzig University Library, http://ub.uni-leipzig.de
#                    The Finc Authors, http://finc.info
#                    Martin Czygan, <martin.czygan@uni-leipzig.de>
#
# This file is part of some open source application.
#
# Some open source application is free software: you can redistribute
# it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, either
# version 3 of the License, or (at your option) any later version.
#
# Some open source application is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
#
# @license GPL-3.0+ <http://spdx.org/licenses/GPL-3.0+>

"""
Turn task dependencies into pretty graphs.

Usage: taskdeps-dot TASKNAME

Example outputs images: http://imgur.com/a/12Dag, http://i.imgur.com/8bFvSvN.gif
"""

from __future__ import print_function
from siskin.utils import pairwise, random_string
from luigi.task import Register
from siskin.sources import *
from siskin.workflows import *
import collections
import re
import sys

# task -> deps graph
g = collections.defaultdict(set)
seen = set()

def iterdeps(task):
    """
    Collect dependencies recursively and store them in the global graph `g`.
    """
    for dependency in task.deps():
        taskname = (task.task_family,)
        depname = (dependency.task_family,)

        g[taskname].add(depname)
        if dependency not in seen:
        	seen.add(dependency)
        	iterdeps(dependency)

def simpleformat(graph):
    """ Format graph as dot. Omit parameters - makes some graphs much smaller. Example: http://imgur.com/a/hxJqv """
    s = 'digraph %s {' % random_string()
    for task, deps in g.iteritems():
        for dep in deps:
            s = s + """\t"%s" [fontname="Helvetica"]; """ % task[0]
            s = s + """\t"%s" [fontname="Helvetica"]; """ % dep[0]
            s = s + """\t"%s" -> "%s"; """ % (task[0], dep[0])
            s = s + "\n"
    s = s + '}'
    return s

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('taskdeps-dot TASKNAME', file=sys.stderr)
        sys.exit(1)

    taskname = sys.argv[1]

    if not taskname in Register.task_names():
        print('no such task: %s' % taskname, file=sys.stderr)
        sys.exit(1)

    # workaround for #1
    ignore = ['--local-scheduler', '--no-lock', '--parallel-scheduling',
              '--assistant', '--scheduler-record-task-history']
    args = [arg for arg in sys.argv[2:] if not arg in ignore]

    kwargs = dict((k.lstrip('--').replace('-', '_'), v) for k, v in pairwise(args))

    klass = Register.get_task_cls(taskname)
    task = klass(**kwargs)
    iterdeps(task)

    print(simpleformat(g))
