# pip install sparqlwrapper
# https://rdflib.github.io/sparqlwrapper/

# import libraries that need to be installed prior to running this code
import sys
import folium
from folium.plugins import MarkerCluster
# their are several Python packages that can be used to collect data from Wikidata, SPARQLwrapper is suggested by the query.wikidata service itself when you copy the Sparql query below (between """), paste it in https://query.wikidata.org/, and run the query and export results to Python.
# folium is the equivalent of Leaflet (which is designed in Javascript) for Python 
from SPARQLWrapper import SPARQLWrapper, JSON

endpoint_url = "https://query.wikidata.org/sparql" # defines query.wikidata as Sparql endpoint

# below is the Sparql query sent to defined endpoint
# sparql query here selects all items that are instances (P31) of war cemeteries and are administrated (P625) by the German War Graves Commission (Q708567)
# all items come along with their location (latitude and longitude) 

query = """
SELECT DISTINCT ?item ?itemLabel ?coords ?lat ?long 
WHERE {
  ?item p:P31/ps:P31/wdt:279* wd:Q1241568 .
  ?item wdt:P137 wd:Q708567 .
  ?item p:P625 ?coords_sample . 
  {
    SELECT (SAMPLE(?coords_stmt) AS ?coords_sample) {
      ?place p:P31/ps:P31/wdt:279* wd:Q1241568 ;
             p:P625 ?coords_stmt .
    } GROUP BY ?place
  }
  ?coords_sample ps:P625 ?coords;
                 psv:P625 [
                   wikibase:geoLatitude ?lat;
                   wikibase:geoLongitude ?long
                 ] .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY ?placeLabel
"""

# this function uses the sparql query above to retrieve results from Wikidata in a Json format
def get_results(endpoint_url, query): 
# "Requests made against the Wikibase REST API must contain a user agent as per the user-agent policy for Wikimedia sites" (https://www.wikidata.org/wiki/Wikidata:REST_API/Authentication)
    user_agent = "war_cemeteries/1.0 (belvezedamien@gmail.com)"
    sparql = SPARQLWrapper(endpoint_url, agent=user_agent)
    sparql.setQuery(query)
    sparql.setReturnFormat(JSON)
    return sparql.query().convert()

# query's output is set as results variable
results = get_results(endpoint_url, query)

# uses folium to design a map centered on the coordinates 47°N, 1°W (France) with a level of focus of 5 (continent scale)
map = folium.Map(location=[47, 1], zoom_start=5)
marker_cluster = MarkerCluster().add_to(map)

# for each line in results dataframe, a marker is created with the coordinates found in lat and long columns, the item_label (name of the war cemetery) is displayed in a popup
for result in results["results"]["bindings"]:
    item_label = result.get("itemLabel", {}).get("value", "")
    latitude = float(result.get("lat", {}).get("value", "0"))
    longitude = float(result.get("long", {}).get("value", "0"))
    
    folium.Marker(
        location=[latitude, longitude],
        popup=item_label
    ).add_to(marker_cluster)
# finally saves the map output in a html file 
map.save("../output/python_map.html")