/*******************************************************************************
 * Copyright 2014 University of Southern California
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * 	http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * This code was developed by the Information Integration Group as part 
 * of the Karma project at the Information Sciences Institute of the 
 * University of Southern California.  For more information, publications, 
 * and related projects, please see: http://www.isi.edu/integration
 ******************************************************************************/
package edu.isi.karma.kr2rml.writer;

import java.io.PrintWriter;
import java.net.URI;
import java.util.HashSet;
import java.util.Set;

import org.json.JSONArray;
import org.json.JSONObject;

import edu.isi.karma.kr2rml.PredicateObjectMap;
import edu.isi.karma.modeling.Uris;

public class JSONKR2RMLRDFWriter extends SFKR2RMLRDFWriter<JSONObject> {

	public JSONKR2RMLRDFWriter (PrintWriter outWriter) {
		super(outWriter);
	}
	
	public JSONKR2RMLRDFWriter (PrintWriter outWriter, String baseURI) {
		super(outWriter, baseURI);
	}

	@Override
	protected void addValue(PredicateObjectMap pom, JSONObject subject, String predicateUri, Object object) {
		if (subject.has(shortHandURIGenerator.getShortHand(predicateUri).toString()) || predicateUri.contains(Uris.RDF_TYPE_URI)) {
			String shortHandPredicateURI = shortHandURIGenerator.getShortHand(predicateUri).toString();
			addValueToArray(pom, subject, object,
					shortHandPredicateURI);
		}
		else
		{
			subject.put(shortHandURIGenerator.getShortHand(predicateUri).toString(), object);
		}
	}

	@Override
	protected void addValueToArray(PredicateObjectMap pom, JSONObject subject, Object object,
			String shortHandPredicateURI) {
		JSONArray array = null;
		if(subject.has(shortHandPredicateURI))
		{
			Object obj = subject.get(shortHandPredicateURI);
			if(obj != null)
			{
				if (obj instanceof JSONArray) {
					array = (JSONArray) obj;
				}
				else{
					array = new JSONArray();
					array.put(obj);
				}
			}
			else
			{
				array = new JSONArray();
			}
		}
		else
		{
			array = new JSONArray();
		}
		if (object instanceof String) {
			String t = ((String)object).trim();
			if (t.startsWith("<") && t.endsWith(">")) {
				t = t.substring(1, t.length() - 1);
				try {
					URI uri = new URI(t);
					if (!uri.isAbsolute())
						t = baseURI + t;
				}catch(Exception e) {
					
				}
			}
			object = t;
		}
		array.put(object);
		subject.put(!shortHandPredicateURI.equalsIgnoreCase("rdf:type")?shortHandPredicateURI: "@type", array);
	}

	@Override
	public void finishRow() {

	}

	@Override
	public void flush() {
		//		finishRow();
		outWriter.flush();
	}

	@Override
	public void close() {
		for(JSONObject value : rootObjects.values())
		{
			collapseSameType(value);
			if (!firstObject) {
				outWriter.println(",");
			}
			firstObject = false;
			outWriter.print(value.toString(4));
		}
		outWriter.println("");
		outWriter.println("]");
		outWriter.close();
	}

	@Override
	protected void collapseSameType(JSONObject obj) {
		for (Object key : obj.keySet()) {
			Object value = obj.get((String)key);
			if (value instanceof JSONArray) {
				JSONArray array = (JSONArray)value;
				Set<Object> types = new HashSet<Object>();
				int length = array.length();
				for (int i = 0; i < length; i++) {
					Object o = array.remove(0);
					if (o instanceof JSONObject) {
						collapseSameType((JSONObject) o);
					}					
					types.add(o);	
				}
				for (Object type : types) {
					array.put(type);
				}
			}
			if (value instanceof JSONObject)
				collapseSameType((JSONObject)value);
		}
	}

	@Override
	protected void initializeOutput() {
		outWriter.println("[");

	}


	@Override
	public JSONObject getNewObject(String triplesMapId, String subjUri) {
		JSONObject object = new JSONObject();
		subjUri.trim();
		if (subjUri.startsWith("<") && subjUri.endsWith(">")) {
			subjUri = subjUri.substring(1, subjUri.length() - 1);
			try {
				URI uri = new URI(subjUri);
				if (!uri.isAbsolute())
					subjUri = baseURI + subjUri;
			}catch(Exception e) {
				
			}
		}
		object.put("@id", subjUri);
		return object;
	}

}

@@ -1522,19 +1522,18 @@
 );%0D%0A%09%7D%0D%0A
-%09
 %0D%0A
+
 %09public 
@@ -2992,23 +2992,18 @@
 n e) %7B%0D%0A
-%09%09%09%09%09
 %0D%0A
+
 %09%09%09%09%7D%0D%0A%09
@@ -4115,24 +4115,54 @@
 );%09%0D%0A%09%09%09%09%7D%0D%0A
+%09%09%09%09if (types.size() %3E 1) %7B%0D%0A%09
 %09%09%09%09for (Obj
@@ -4178,24 +4178,25 @@
 : types) %7B%0D%0A
+%09
 %09%09%09%09%09array.p
@@ -4202,24 +4202,155 @@
 put(type);%0D%0A
+%09%09%09%09%09%7D%0D%0A%09%09%09%09%7D%0D%0A%09%09%09%09else if (types.iterator().hasNext())%7B%0D%0A%09%09%09%09%09Object o = types.iterator().next();%0D%0A%09%09%09%09%09obj.put((String)key, o);%0D%0A
 %09%09%09%09%7D%0D%0A%09%09%09%7D%0D
@@ -4920,20 +4920,16 @@
 n e) %7B%0D%0A
-%09%09%09%09
 %0D%0A%09%09%09%7D%0D%0A

Fix WK-273