package edu.isi.karma.kr2rml;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.json.JSONObject;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;

import edu.isi.karma.modeling.Uris;

public class ContextGenerator {
	private Model model;
	private boolean isGenerateAtIdType;
	Map<String, Set<ContextObject>> contextMapping = new HashMap<String, Set<ContextObject>>();
	private abstract class ContextObject {
		public String prefix;
		public String URI;
		public ContextObject(String prefix, String URI) {
			this.prefix = prefix;
			this.URI = URI;
		}

		@Override
		public int hashCode() {
			return prefix.hashCode() * URI.hashCode();		
		}

		@Override
		public boolean equals(Object o) {
			if (o instanceof ContextObject) {
				return ((ContextObject) o).URI == URI;
			}
			return false;
		}

		public abstract boolean isClassContext();
		public abstract String getDataType();
	}

	private class ClassContextObject extends ContextObject {
		public ClassContextObject(String prefix, String URI) {
			super(prefix, URI);
		}

		@Override
		public boolean isClassContext() {
			return true;
		}

		@Override
		public String getDataType() {
			return null;
		}

	}

	private class PredicateContextObject extends ContextObject {
		public String dataType;
		public PredicateContextObject(String prefix, String URI, String dataType) {
			super(prefix, URI);
			this.dataType = dataType;
		}
		@Override
		public boolean isClassContext() {
			return false;
		}
		@Override
		public String getDataType() {
			return dataType;
		}

	}
	public ContextGenerator(Model model, boolean isGenerateAtIdType) {
		this.model = model;
		this.isGenerateAtIdType = isGenerateAtIdType;
	}
	public JSONObject generateContext() {
		StmtIterator itr = model.listStatements();
		JSONObject obj = new JSONObject();
		while(itr.hasNext()) {
			Statement stmt = itr.next();
			if (stmt.getPredicate().getURI().equals(Uris.RR_CLASS_URI)) {
				if (stmt.getObject().isURIResource()) {
					String shortForm = model.shortForm(stmt.getObject().toString());
					String fullURI = stmt.getObject().toString();
					if (!shortForm.equals(fullURI)) {
						String postfix = shortForm.substring(shortForm.lastIndexOf(":") + 1);
						String prefix = shortForm.substring(0, shortForm.lastIndexOf(":"));
						Set<ContextObject> existPrefixes = contextMapping.get(postfix);
						if (existPrefixes == null) {
							existPrefixes = new HashSet<ContextObject>();
						}
						existPrefixes.add(new ClassContextObject(prefix, fullURI));
						contextMapping.put(postfix, existPrefixes);
					}
				}
			}
			if (stmt.getPredicate().getURI().equals(Uris.RR_PREDICATE_URI)) {
				if (stmt.getObject().isURIResource()) {
					Property objectMapProp = model.getProperty(Uris.RR_OBJECTMAP_URI);
					Property dataTypeProp = model.getProperty(Uris.RR_DATATYPE_URI);
					RDFNode node = stmt.getSubject().getProperty(objectMapProp).getObject();
					String dataType = null;
					if (node != null && node.isResource()) {
						Statement s = node.asResource().getProperty(dataTypeProp);
						if (s != null) {
							dataType = model.shortForm(s.getObject().toString());
						}
					}
					String shortForm = model.shortForm(stmt.getObject().toString());
					String fullURI = stmt.getObject().toString();
					if (!shortForm.equals(fullURI)) {
						String postfix = shortForm.substring(shortForm.lastIndexOf(":") + 1);
						String prefix = shortForm.substring(0, shortForm.lastIndexOf(":"));
						Set<ContextObject> existPrefixes = contextMapping.get(postfix);
						if (existPrefixes == null) {
							existPrefixes = new HashSet<ContextObject>();
						}
						existPrefixes.add(new PredicateContextObject(prefix, fullURI, dataType));
						contextMapping.put(postfix, existPrefixes);
					}
				}
			}
		}
		for (Entry<String, Set<ContextObject>> entry : contextMapping.entrySet()) {
			Set<ContextObject> prefixes = entry.getValue();
			if (prefixes.size() > 1) {
				for (ContextObject prefix : prefixes) {
					String prefixURI = prefix.URI.replace(entry.getKey(), "");
					obj.put(prefix.prefix, prefixURI);
				}
			}
			else {
				for (ContextObject prefix : prefixes) {
					JSONObject t = new JSONObject();
					t.put("@id", prefix.URI);
					if (prefix.isClassContext()) {
						t.put("@type", "@id");
					}
					String dataType = prefix.getDataType();
					if (dataType != null) {
						String p = dataType.substring(0, dataType.lastIndexOf(":"));
						obj.put(p, model.getNsPrefixURI(p));
						t.put("@type", dataType);
					}
					obj.put(entry.getKey(), t);
				}
			}
		}
		if (isGenerateAtIdType) {
			obj.put("url", "@id");
			obj.put("a", "@type");
		}
		JSONObject top = new JSONObject();
		top.put("@context", obj);
		return top;
	}
}

@@ -4844,17 +4844,17 @@
 .put(%22ur
-l
+i
 %22, %22@id%22

change from url to uri