import requests

# helper function to raise exception if the REST endpoint returns an
# unexpected status code
def assert_reponse_ok(response, message):
    if not response.ok:
        raise Exception(
            message + "\nStatus received={}\n{}".format(response.status_code, response.text))

rdfox_server = "http://localhost:8080"

# Create the datastore
response = requests.post(
    rdfox_server + "/datastores/family", params={'type': 'par-complex-nn'})
assert_reponse_ok(response, "Failed to create datastore.")

# List datastores
response = requests.get(rdfox_server + "/datastores")
assert_reponse_ok(response, "Failed to obtain list of datastores")
print("== Datastore list ==")
print(response.text)

# Add facts
turtle_data = """
@prefix : <https://oxfordsemantic.tech/RDFox/getting-started/> .

:peter :forename "Peter" ;
    a :Person ;
    :marriedTo :lois ;
    :gender "male" .

:lois :forename "Lois" ;
    a :Person ;
    :gender "female" .

:meg :forename "Meg" ;
    a :Person ;
    :hasParent :lois, :peter ;
    :gender "female" .

:chris :forename "Chris" ;
    a :Person ;
    :hasParent :peter ;
    :gender "male" .

:stewie :forename "Stewie" ;
    a :Person ;
    :hasParent :lois ;
    :gender "male" .

:brian :forename "Brian" . # Brian is a dog
"""

response = requests.post(
    rdfox_server + "/datastores/family/content", data=turtle_data)
assert_reponse_ok(response, "Failed to add facts to datastore.")

# List facts
response = requests.get(
    rdfox_server + "/datastores/family/content", headers={"Accept": "text/turtle"})
assert_reponse_ok(response, "Failed to obtain facts from datastore.")
print("== Facts imported ==")
print(response.text)

# Issue select query
sparql_text = "PREFIX : <https://oxfordsemantic.tech/RDFox/getting-started/> " \
    "SELECT ?p ?n WHERE { ?p a :Person . ?p :forename ?n }"
response = requests.get(
    rdfox_server + "/datastores/family/sparql", params={"query": sparql_text})
assert_reponse_ok(response, "Failed to run select query.")
print("== Initial query result ==")
print(response.text)

# Issue insert
sparql_insert = "PREFIX : <https://oxfordsemantic.tech/RDFox/getting-started/> " \
    "INSERT { ?x :marriedTo ?y } WHERE { ?y :marriedTo ?x }"
response = requests.post(
    rdfox_server + "/datastores/family/sparql", data={"update": sparql_insert})
assert_reponse_ok(response, "Failed to insert fact via sparql.")

# Add rule
datalog_rule = "@PREFIX : <https://oxfordsemantic.tech/RDFox/getting-started/> . " \
    "[?p, :hasChild, ?c] :- [?c, :hasParent, ?p] ."
response = requests.post(
    rdfox_server + "/datastores/family/content", data=datalog_rule)
assert_reponse_ok(response, "Failed to add rule.")

# Check rule exists by listing rules.
response = requests.get(rdfox_server + "/datastores/family/content",
                        headers={"Content-Type": "application/x.datalog"})
assert_reponse_ok(response, "Failed to list rules.")
print("== Rules listing (after adding rule) ==")
print(response.text)

# Query to confirm rule
sparql_text = "PREFIX : <https://oxfordsemantic.tech/RDFox/getting-started/> " \
    "SELECT ?p ?c WHERE { ?p :hasChild ?c }"
response = requests.get(
    rdfox_server + "/datastores/family/sparql", params={"query": sparql_text})
assert_reponse_ok(response, "Failed to run select query.")
print("== Query for derived facts ==")
print(response.text)

# Delete fact
datalog_text = "@PREFIX : <https://oxfordsemantic.tech/RDFox/getting-started/> . " \
    "[:stewie, :hasParent, :lois] ."
response = requests.patch(
    rdfox_server + "/datastores/family/content", params={"mode": "delete"}, data=datalog_text)
assert_reponse_ok(response, "Failed to delete fact.")

# Query to confirm derived facts updated (stewie is no longer a child of lois)
sparql_text = "PREFIX : <https://oxfordsemantic.tech/RDFox/getting-started/> " \
    "SELECT ?p ?c WHERE { ?p :hasChild ?c }"
response = requests.get(
    rdfox_server + "/datastores/family/sparql", params={"query": sparql_text})
assert_reponse_ok(response, "Failed to run select query.")
print("== Query for updated derived facts ==")
print(response.text)

# delete rule
datalog_rule = "@PREFIX : <https://oxfordsemantic.tech/RDFox/getting-started/> . " \
    "[?p, :hasChild, ?c] :- [?c, :hasParent, ?p] ."
response = requests.patch(
    rdfox_server + "/datastores/family/content", params={"mode": "delete"}, data=datalog_rule)
assert_reponse_ok(response, "Failed to delete rule.")

# list rules after deletion
response = requests.get(rdfox_server + "/datastores/family/content",
                        headers={"Accept": "application/x.datalog"})
assert_reponse_ok(response, "Failed to list rules.")
print("== Rules listing (after deleting rule) ==")
print(response.text)
