import subprocess
import ops_cache
import copy
import tempfile
import os

def get_emoji_for_node(node):
    if node['class'] == 'listing':
        return '🪧 '

    if 'podcast' in node['shallow_tags']:
        return '🎙️ '

    if 'webradio' in node['shallow_tags']:
        return '📻 '

    if 'blog' in node['shallow_tags']:
        return '📰 '

    return ''

@ops_cache.cache
def gen(headline_id, graph, doc_to_headline_remapping):
    reference_node = headline_id
    font_name = 'monospace'

    linked_from_internal = set()
    g = copy.deepcopy(graph)

    if 'id:' + reference_node in doc_to_headline_remapping:
        reference_node = doc_to_headline_remapping['id:' + reference_node].split(':', 1)[1]

    centered_graph = { reference_node: g[reference_node] }
    for l in g[reference_node]['links']:
        lt = l['target']
        if lt.startswith("id:"):
            lt = lt[3:]
        linked_from_internal.add(lt)
    del g[reference_node]
    new_nodes = True

    in_emacs_tree = {
        reference_node: set(),
    }

    while new_nodes:
        new_nodes = False
        removed = set()
        for k, v in g.items():
            if 'id:' + k in doc_to_headline_remapping:
                k = doc_to_headline_remapping['id:' + k].split(':', 1)[1]

            for link in v["links"]:
                if link["target"].startswith("id:"):
                    link["target"] = link["target"][3:]
                if link['target'] in centered_graph and link.get('relation') == 'in':
                    centered_graph[k] = v

                    for l in v["links"]:
                        if l.get('relation') == 'in':
                            t = l['target']
                            if t.startswith("id:"):
                                t = t[3:]

                            if '[' in t:
                                # Special case, to be handled on org_rw
                                continue

                            if t not in in_emacs_tree:
                                in_emacs_tree[t] = set()
                            in_emacs_tree[t].add(k)

                    v['links'] = [
                        l for l in v["links"]
                        if l.get('relation') != 'in'
                    ]
                    for l in v['links']:
                        lt = l['target']
                        if lt.startswith("id:"):
                            lt = lt[3:]
                        linked_from_internal.add(lt)

                    removed.add(k)
                    new_nodes = True
                    break
        for k in removed:
            del g[k]

    in_emacs = set(centered_graph.keys())

    # One more round for the rest, not requiring "in"
    for k, v in g.items():
        if 'id:' + k in doc_to_headline_remapping:
            k = doc_to_headline_remapping['id:' + k].split(':', 1)[1]

        backlinked = False
        for link in v["links"]:
            if link["target"].startswith("id:"):
                link["target"] = link["target"][3:]
            if link['target'] in in_emacs:
                centered_graph[k] = v
                backlinked = True
                removed.add(k)
        if not backlinked and (k in linked_from_internal):
            centered_graph[k] = v
            removed.add(k)

    g = centered_graph

    with tempfile.NamedTemporaryFile(suffix='.dot', mode='wt') as f:
        f.write('strict digraph {\n')
        f.write('maxiter=10000\n')
        f.write('splines=curved\n')
        # f.write('splines=spline\n') # Not supported with edges to cluster
        f.write('node[shape=rect, width=0.5, height=0.5]\n')
        f.write('K=0.3\n')
        f.write('edge[len = 1]\n')
        def draw_subgraph(node_id, depth):
            f.write("subgraph cluster_{} {{\n".format(node_id.replace("-", "_")))
            f.write('  URL="./{}.node.html"\n'.format(node_id))
            f.write('  class="{}"\n'.format('cluster-depth-' + str(depth - 1)))
            f.write("  fontname=\"{}\"\n".format(font_name))
            f.write("  label=\"{}\"\n".format(
                get_emoji_for_node(g[node_id]) + g[node_id]['title'].replace("\"", "'")
            ))
            f.write("\n")

            # print("T: {}".format(in_emacs_tree), file=sys.stderr)
            for k in in_emacs_tree[node_id]:
                v = g[k]

                if k in in_emacs_tree:
                    draw_subgraph(k, depth=depth + 1)
                else:
                    print("  _" + k.replace("-", "_")
                          + "[label=\"" + get_emoji_for_node(v) + v["title"].replace("\"", "'") + "\", "
                          + "URL=\"" + k + ".node.html\", "
                          + "fontname=\"" + font_name + "\", "
                          + "class=\"cluster-depth-" + str(depth) + "\""
                          + "];", file=f)


            f.write("\n}\n")

        draw_subgraph(reference_node, 1)

        for k, v in g.items():
            if k not in in_emacs:
                print("_" + k.replace("-", "_")
                      + "[label=\"" + get_emoji_for_node(v) + v["title"].replace("\"", "'") + "\", "
                      + "fontname=\"" + font_name + "\", "
                      + "URL=\"" + k + ".node.html\"];", file=f)

        for k, v in g.items():
            link_src = '_' + k.replace("-", "_")
            if k in in_emacs_tree:
                link_src = 'cluster_{}'.format(k.replace("-", "_"))

            for link in v["links"]:
                if link["target"].startswith("id:"):
                    link["target"] = link["target"][3:]

                if '[' in link['target']:
                    # Special case, to be handled on org_rw
                    continue
                if link['target'] not in g:
                    # Irrelevant
                    continue
                if link['target'] in in_emacs_tree:
                    t = 'cluster_{}'.format(link['target'].replace("-", "_"))
                else:
                    t = "_" + link["target"].replace("-", "_")
                print(link_src + "->" + t, file=f)

        f.write('}\n')
        f.flush()

        with tempfile.NamedTemporaryFile(suffix='.svg') as fsvg:
            subprocess.call(['fdp', f.name, '-Tsvg', '-o', fsvg.name])
            fsvg.seek(0)
            return fsvg.read().decode()