// Downloaded apache-jena-4.4.0.tar.gz from https://jena.apache.org/download/ and extracted it.
// cheeses-0.1.ttl is also taken from the downloaded archive.
// Run with: java -classpath apache-jena-4.4.0/lib/*:. SimpleSparqlServer.java

import java.io.*;
import com.sun.net.httpserver.*;
import org.apache.jena.riot.*;
import static java.nio.charset.StandardCharsets.UTF_8;

class SimpleSparqlServer {
	public static void main(String[] args) throws InterruptedException, IOException {
		System.out.println("Opening database...");
		var dir = "data";
		var dataset = org.apache.jena.tdb2.TDB2Factory.connectDataset(dir);
		
		System.err.println("Loading cheeses-0.1.ttl...");
		dataset.executeWrite(() -> {
			var model = dataset.getDefaultModel();
			try {
				model.read(new FileInputStream("cheeses-0.1.ttl"), null, "TTL");
			} catch (FileNotFoundException e) {
				System.err.println(e);
			}
			model.close();
		});
		
		System.out.println("Starting webserver...");
		var server = HttpServer.create(new java.net.InetSocketAddress("localhost", 8080), 0);
		
		server.createContext("/", con -> {
			// GET /  →  show website with query form
			con.getResponseHeaders().set("Content-Type", "text/html; charset=utf-8");
			con.sendResponseHeaders(200, 0);
			con.getResponseBody().write("""
				<!DOCTYPE html>
				<meta charset=utf-8>
				<title>SPARQL Webserver</title>
				
				<form name=query>
					<textarea name=query style="display: block; min-width: 60em; min-height: 20em;">
				CONSTRUCT {
					?s ?p ?o
				} WHERE {
					?s ?p ?o .
					FILTER(?s = <http://data.kasabi.com/dataset/cheese/halloumi>)
				}
					</textarea>
					<button>go</button>
					<output name=result style="display: block; white-space: pre-wrap;"></output>
					
					<script type=module>
						document.forms.query.addEventListener("submit", event => {
							event.preventDefault()
							const body = Object.fromEntries(new FormData(document.forms.query).entries())
							fetch("/query", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) })
								.then(res => res.text()).then(text => document.forms.query.result.textContent = text)
						})
					</script>
				</form>
				""".getBytes(UTF_8));
			con.close();
		});
		
		server.createContext("/query", con -> {
			// POST /query { "query": "..." }  →  query result as expanded JSON-LD
			dataset.executeRead(() -> {
				var body = org.apache.jena.atlas.json.JSON.parse(con.getRequestBody());
				var queryCode = body.getString("query");
				
				try {
					try (var query = org.apache.jena.query.QueryExecution.create(queryCode, dataset)) {
						var model = query.execConstruct();
						con.sendResponseHeaders(200, 0);
						RDFWriter.create(model).format(RDFFormat.JSONLD_EXPAND_PRETTY).output(con.getResponseBody());
					} catch (org.apache.jena.query.QueryParseException e) {  // thrown on SPARQL syntax error
						con.getResponseHeaders().set("Content-Type", "text/plain");
						con.sendResponseHeaders(500, 0);
						con.getResponseBody().write(e.getMessage().getBytes(UTF_8));
					} finally {
						con.close();
					}
				} catch (IOException ignored) {
				}
			});
		});
		
		server.start();
		System.out.println("Ready, accepting connections :)");
	}
}