#!/usr/bin/env python3

import sys
import json
import rdflib
import rdflib.plugins.sparql as sparql

RELS_TO_DRAW = ['isWifeOf', 'isMotherOf', 'isFatherOf', 'isHusbandOf', 'isSpouseOf']
RELS_TO_INFER = ['hasGrandParent', 'isGrandParentOf', 'hasGreatGrandParent',
                 'isGreatGrandParentOf', 'isUncleOf', 'hasUncle',
                 'isGreatUncleOf', 'hasGreatUncle', 'isAuntOf', 'hasAunt',
                 'isGreatAuntOf', 'hasGreatAunt',
                 'isBrotherOf', 'isSisterOf', 'isSiblingOf',
                 'isFirstCousinOf', 'isSecondCousinOf', 'isThirdCousinOf']

RELS_OF_INTEREST = RELS_TO_DRAW + RELS_TO_INFER

try:
    workpath = sys.argv[1]
except IndexError:
    sys.exit("No path defined!")
try:
    recursion_limit = int(sys.argv[2])
except IndexError:
    recursion_limit = 0

if recursion_limit > 0:
    sys.setrecursionlimit(recursion_limit)

g = rdflib.Graph()
g.parse(workpath, format="turtle")

fhkb_str = "http://www.example.com/genealogy.owl#"
schema_str = "https://schema.org/"

FHKB = rdflib.Namespace(fhkb_str)
SCHEMA_ORG = rdflib.Namespace(schema_str)

def dump(uriref):
    if uriref.__contains__('#'):
        return uriref.split('#')[-1]
    return uriref.split('/')[-1]

graph = {}
graph['nodes'] = []
graph['edges'] = []

nodes = {}

q = sparql.prepareQuery(
"""PREFIX fhkb:<http://www.example.com/genealogy.owl#> 
   SELECT ?person ?pred ?obj
   WHERE { 
       ?person a fhkb:Person ; 
       ?pred ?obj .
    } 
    ORDER BY ?person""")

for rel in RELS_OF_INTEREST:
    pred = rdflib.URIRef("{}{}".format(fhkb_str, rel))
    relation_query_results = g.query(q, initBindings={'pred': pred})
    for (subj, pred, obj) in relation_query_results:
        graph['edges'].append(
            {
                'data': {
                    'group': 'edges',
                    'id': f'{dump(subj)}-{dump(pred)}-{dump(obj)}',
                    'source': dump(subj),
                    'target': dump(obj),
                    'type': dump(pred)
                }
            })

q_details = sparql.prepareQuery(
"""PREFIX fhkb:<http://www.example.com/genealogy.owl#>
   SELECT ?person ?pred ?obj
   WHERE { 
       ?person a fhkb:Person ; 
           ?pred ?obj . 
   FILTER NOT EXISTS {
       ?person ?testPred ?obj .
       VALUES ?testPred {
           fhkb:isWifeOf
           fhkb:isMotherOf
           fhkb:isFatherOf
           fhkb:isHusbandOf
           fhkb:isSpouseOf
           fhkb:hasGrandParent
           fhkb:isGrandParentOf
           fhkb:hasGreatGrandParent
           fhkb:isGreatGrandParentOf
           fhkb:isUncleOf
           fhkb:hasUncle
           fhkb:isGreatUncleOf
           fhkb:hasGreatUncle
           fhkb:isAuntOf
           fhkb:hasAunt
           fhkb:isGreatAuntOf
           fhkb:hasGreatAunt
           fhkb:isBrotherOf
           fhkb:isSisterOf
           fhkb:isSiblingOf
           fhkb:isFirstCousinOf
           fhkb:isSecondCousinOf
           fhkb:isThirdCousinOf

           fhkb:hasRelation
           fhkb:isPartnerIn
           fhkb:isMalePartnerIn
           fhkb:isFemalePartnerIn
           fhkb:isBloodrelationOf
       }
   }
} 
ORDER BY ?person"""
)

person_query_results = g.query(q_details)    
for (subj, pred, obj) in person_query_results: 
    node = nodes.get(dump(subj), {
                'data': {
                    'label': '',
                    'degree': 0,
                    'size': 10,
                    'alternateNames': [],
                    'honorificPrefixes': [],
                    'honorificSuffixes': [],
                    'images': [],
                    'id': dump(subj),
                }}) 
    
    if pred == FHKB.Sex:
        node['data'][dump(pred)] = dump(obj)
    elif pred.startswith(SCHEMA_ORG):
        if dump(pred) == 'honorificSuffix':
            node['data']['honorificSuffixes'].append(obj)
        elif dump(pred) == 'honorificPrefix':
            node['data']['honorificPrefixes'].append(obj)
        elif dump(pred) == 'alternateName':
            node['data']['alternateNames'].append(obj)
        elif dump(pred) == 'image':
            node['data']['images'].append(obj)
        else:
            node['data'][dump(pred)] = obj
    elif pred == rdflib.RDFS.label:
        node['data']['label'] = obj
    else:
        continue
    
    nodes[dump(subj)] = node

graph['nodes'] = list(nodes.values())

print(json.dumps(graph, indent=0))
sys.exit(0)

[((30, 4, 30, 18), 'rdflib.Graph', 'rdflib.Graph', ({}, {}), '()', False, 'import rdflib\n'), ((36, 7, 36, 33), 'rdflib.Namespace', 'rdflib.Namespace', ({(36, 24, 36, 32): 'fhkb_str'}, {}), '(fhkb_str)', False, 'import rdflib\n'), ((37, 13, 37, 41), 'rdflib.Namespace', 'rdflib.Namespace', ({(37, 30, 37, 40): 'schema_str'}, {}), '(schema_str)', False, 'import rdflib\n'), ((50, 4, 57, 24), 'rdflib.plugins.sparql.prepareQuery', 'sparql.prepareQuery', ({(51, 0, 57, 23): '"""PREFIX fhkb:<http://www.example.com/genealogy.owl#> \n   SELECT ?person ?pred ?obj\n   WHERE { \n       ?person a fhkb:Person ; \n       ?pred ?obj .\n    } \n    ORDER BY ?person"""'}, {}), '(\n    """PREFIX fhkb:<http://www.example.com/genealogy.owl#> \n   SELECT ?person ?pred ?obj\n   WHERE { \n       ?person a fhkb:Person ; \n       ?pred ?obj .\n    } \n    ORDER BY ?person"""\n    )', True, 'import rdflib.plugins.sparql as sparql\n'), ((74, 12, 116, 1), 'rdflib.plugins.sparql.prepareQuery', 'sparql.prepareQuery', ({(75, 0, 115, 19): '"""PREFIX fhkb:<http://www.example.com/genealogy.owl#>\n   SELECT ?person ?pred ?obj\n   WHERE { \n       ?person a fhkb:Person ; \n           ?pred ?obj . \n   FILTER NOT EXISTS {\n       ?person ?testPred ?obj .\n       VALUES ?testPred {\n           fhkb:isWifeOf\n           fhkb:isMotherOf\n           fhkb:isFatherOf\n           fhkb:isHusbandOf\n           fhkb:isSpouseOf\n           fhkb:hasGrandParent\n           fhkb:isGrandParentOf\n           fhkb:hasGreatGrandParent\n           fhkb:isGreatGrandParentOf\n           fhkb:isUncleOf\n           fhkb:hasUncle\n           fhkb:isGreatUncleOf\n           fhkb:hasGreatUncle\n           fhkb:isAuntOf\n           fhkb:hasAunt\n           fhkb:isGreatAuntOf\n           fhkb:hasGreatAunt\n           fhkb:isBrotherOf\n           fhkb:isSisterOf\n           fhkb:isSiblingOf\n           fhkb:isFirstCousinOf\n           fhkb:isSecondCousinOf\n           fhkb:isThirdCousinOf\n\n           fhkb:hasRelation\n           fhkb:isPartnerIn\n           fhkb:isMalePartnerIn\n           fhkb:isFemalePartnerIn\n           fhkb:isBloodrelationOf\n       }\n   }\n} \nORDER BY ?person"""'}, {}), '(\n    """PREFIX fhkb:<http://www.example.com/genealogy.owl#>\n   SELECT ?person ?pred ?obj\n   WHERE { \n       ?person a fhkb:Person ; \n           ?pred ?obj . \n   FILTER NOT EXISTS {\n       ?person ?testPred ?obj .\n       VALUES ?testPred {\n           fhkb:isWifeOf\n           fhkb:isMotherOf\n           fhkb:isFatherOf\n           fhkb:isHusbandOf\n           fhkb:isSpouseOf\n           fhkb:hasGrandParent\n           fhkb:isGrandParentOf\n           fhkb:hasGreatGrandParent\n           fhkb:isGreatGrandParentOf\n           fhkb:isUncleOf\n           fhkb:hasUncle\n           fhkb:isGreatUncleOf\n           fhkb:hasGreatUncle\n           fhkb:isAuntOf\n           fhkb:hasAunt\n           fhkb:isGreatAuntOf\n           fhkb:hasGreatAunt\n           fhkb:isBrotherOf\n           fhkb:isSisterOf\n           fhkb:isSiblingOf\n           fhkb:isFirstCousinOf\n           fhkb:isSecondCousinOf\n           fhkb:isThirdCousinOf\n\n           fhkb:hasRelation\n           fhkb:isPartnerIn\n           fhkb:isMalePartnerIn\n           fhkb:isFemalePartnerIn\n           fhkb:isBloodrelationOf\n       }\n   }\n} \nORDER BY ?person"""\n    )', True, 'import rdflib.plugins.sparql as sparql\n'), ((155, 0, 155, 11), 'sys.exit', 'sys.exit', ({(155, 9, 155, 10): '(0)'}, {}), '(0)', False, 'import sys\n'), ((28, 4, 28, 42), 'sys.setrecursionlimit', 'sys.setrecursionlimit', ({(28, 26, 28, 41): 'recursion_limit'}, {}), '(recursion_limit)', False, 'import sys\n'), ((154, 6, 154, 33), 'json.dumps', 'json.dumps', (), '', False, 'import json\n'), ((21, 4, 21, 32), 'sys.exit', 'sys.exit', ({(21, 13, 21, 31): '"""No path defined!"""'}, {}), "('No path defined!')", False, 'import sys\n')]