/*******************************************************************************
 *  Copyright (c) 2012-2014 SAP SE.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  Contributors:
 *  SAP SE - initial API and implementation and/or initial documentation
 *
 *******************************************************************************/
package org.eclipse.ogee.client.parser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import org.eclipse.ogee.client.exceptions.MarshalerException;
import org.eclipse.ogee.client.exceptions.ParserException;
import org.eclipse.ogee.client.jsonsimple.JSONArray;
import org.eclipse.ogee.client.jsonsimple.JSONObject;
import org.eclipse.ogee.client.jsonsimple.JSONValue;
import org.eclipse.ogee.client.jsonsimple.parser.JSONParser;
import org.eclipse.ogee.client.jsonsimple.parser.ParseException;
import org.eclipse.ogee.client.model.edmx.Edmx;
import org.eclipse.ogee.client.model.generic.ComplexTypeCollection;
import org.eclipse.ogee.client.model.generic.ODataCollection;
import org.eclipse.ogee.client.model.generic.ODataEntry;
import org.eclipse.ogee.client.model.generic.ODataProperty;
import org.eclipse.ogee.client.model.generic.ServiceDocument;
import org.eclipse.ogee.client.model.json.ODataCollectionJson;
import org.eclipse.ogee.client.model.json.ODataEntryJson;
import org.eclipse.ogee.client.model.json.ODataJsonTags;
import org.eclipse.ogee.client.model.json.ODataLinkJson;
import org.eclipse.ogee.client.model.json.ODataPropertyJson;
import org.eclipse.ogee.client.model.json.ServiceDocumentJson;
import org.eclipse.ogee.client.nls.messages.Messages;
import org.eclipse.ogee.client.parser.impl.Marshaller;
import org.eclipse.ogee.client.parser.impl.TypeConverter;

/**
 * JSON specific implementation of IODataParser
 */
public class ODataJSONParser implements IODataParser {
	private static final String ENTITY_SETS_KEY = "EntitySets"; //$NON-NLS-1$
	private final static Logger LOGGER = Logger.getLogger(ODataJSONParser.class
			.getName());
	private TypeConverter typeConverter = TypeConverter.JSON;

	/**
	 * Constructor
	 */
	public ODataJSONParser() {
		super();
	}

	@Override
	public ODataEntry parseODataEntry(String data) throws ParserException {
		JSONObject jsonObject = parseJSONObject(data);

		jsonObject = stripDtag(jsonObject);
		jsonObject = stripResultsTag(jsonObject);

		ODataEntryJson entry = new ODataEntryJson();

		// iterate over the properties
		Set<?> propertySet = ((HashMap<?, ?>) jsonObject).entrySet();

		for (Object property : propertySet) {
			Object key = ((Map.Entry<?, ?>) property).getKey();
			Object value = ((Map.Entry<?, ?>) property).getValue();
			populateODataEntry(entry, key, value);
		}
		return entry;
	}

	/**
	 * @param jsonObject
	 * @return - the given JSON object without the 'results' tag.
	 */
	private JSONObject stripResultsTag(JSONObject jsonObject) {
		JSONObject dObject = (JSONObject) jsonObject
				.get(ODataJsonTags.RESULTS_TAG);
		if (dObject != null) {
			return dObject;
		}
		return jsonObject;
	}

	/**
	 * @param jsonObject
	 * @return - the given JSON array without the 'results' tag.
	 */
	private JSONArray stripResultsTagFromJSONArray(JSONObject jsonObject) {
		JSONArray jsonArray = (JSONArray) jsonObject
				.get(ODataJsonTags.RESULTS_TAG);
		if (jsonArray != null) {
			return jsonArray;
		}
		return null;
	}

	/**
	 * @param jsonObject
	 * @return - the given JSON object without the 'd' tag.
	 */
	private JSONObject stripDtag(JSONObject jsonObject) {
		JSONObject dObject = (JSONObject) jsonObject.get(ODataJsonTags.D_TAG);
		if (dObject != null) {
			return dObject;
		}
		return jsonObject;
	}

	/**
	 * Populates OData JSON Entry with the given key and value.
	 * 
	 * @param entry
	 * @param key
	 * @param value
	 * @throws ParserException
	 */
	private void populateODataEntry(ODataEntryJson entry, Object key,
			Object value) throws ParserException {
		if (value == null) {
			entry.putProperty(key.toString(), null);
			return;
		}
		// check if this property is the metadata tag
		if (key.equals(ODataJsonTags.METADATA_TAG)) {
			HashMap<String, String> parsedMetadata = parseMetaData((HashMap<?, ?>) value);
			entry.setMetadata(parsedMetadata);
			entry.setId(parsedMetadata.get(ODataJsonTags.URI_TAG));
			entry.setType(parsedMetadata.get(ODataJsonTags.TYPE_TAG));
		}
		// check if this property is the navigation property
		else if (isLink(value)) {
			ODataLinkJson link = parseLink(key, value);
			entry.addLink(link);
		} else {

			// check if value is complex
			if (isComplexProperty(value)) {
				ODataPropertyJson parsedODataPropertyJson = (ODataPropertyJson) this
						.parseODataProperty(value.toString());
				parsedODataPropertyJson.setName(key.toString());
				entry.putProperty(parsedODataPropertyJson);
			} else if (isCollectionProperty(value)) {
				ODataPropertyJson parsedODataPropertyJson = (ODataPropertyJson) this
						.parseODataProperty(value.toString());

				// Expanded Navigation Property with skipTonken.
				if (parsedODataPropertyJson.getValue() == null) {
					parsedODataPropertyJson = parsedODataPropertyJson
							.getChildDataValue(ODataJsonTags.RESULTS_TAG);
				}

				ODataCollectionJson dataCollectionJson = (ODataCollectionJson) this
						.parseODataCollection(parsedODataPropertyJson
								.getValue());
				parsedODataPropertyJson.setCollectionValue(dataCollectionJson);
				parsedODataPropertyJson.setName(key.toString());
				entry.putProperty(parsedODataPropertyJson);
			} else {
				// handle as simple property
				entry.putProperty(key.toString(), value.toString());
			}
		}
	}

	/**
	 * @param value
	 * @return - true whether the given value is a complex property, and false
	 *         otherwise.
	 */
	private boolean isComplexProperty(Object value) {
		return (value.toString().startsWith("{") && !value.toString().startsWith("{\"results\"")); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * @param value
	 * @return - true whether the given value is a collection property, and
	 *         false otherwise.
	 */
	private boolean isCollectionProperty(Object value) {
		return value.toString().startsWith("{\"results\""); //$NON-NLS-1$
	}

	/**
	 * Parses a link object given its key and value.
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	private ODataLinkJson parseLink(Object key, Object value) {
		Object defered = ((HashMap<?, ?>) value)
				.get(ODataJsonTags.DEFERRED_TAG);
		Object uri = ((HashMap<?, ?>) defered).get(ODataJsonTags.URI_TAG);
		ODataLinkJson link = new ODataLinkJson();
		link.setUri(uri.toString());
		link.setTitle(key.toString());

		return link;
	}

	/**
	 * @param value
	 * @return - true whether the given value is a link, and false otherwise.
	 */
	private boolean isLink(Object value) {
		if (value instanceof Map) {
			if ((((HashMap<?, ?>) value).get(ODataJsonTags.DEFERRED_TAG)) != null) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	/**
	 * Parses the given metadata.
	 * 
	 * @param metadata
	 * @return
	 */
	private HashMap<String, String> parseMetaData(Map<?, ?> metadata) {
		HashMap<String, String> parsedMetadata = new HashMap<String, String>();
		for (Map.Entry<?, ?> entry : metadata.entrySet()) {
			parsedMetadata.put(entry.getKey().toString(), entry.getValue()
					.toString());
		}

		return parsedMetadata;
	}

	@SuppressWarnings("unchecked")
	@Override
	public ODataCollection parseODataCollection(String data)
			throws ParserException {
		LinkedList<ODataEntry> collection = new LinkedList<ODataEntry>();

		JSONObject jsonObject = parseJSONObject(data);

		jsonObject = stripDtag(jsonObject);
		JSONArray jsonArray = stripResultsTagFromJSONArray(jsonObject);

		if (jsonArray == null) {
			return null;
		}

		for (Iterator<JSONObject> iterator = jsonArray.iterator(); iterator
				.hasNext();) {
			JSONObject jsonEntry = iterator.next();
			ODataEntry parsedODataEntry = this.parseODataEntry(jsonEntry
					.toJSONString());
			collection.add(parsedODataEntry);
		}

		return convertToODataCollectionJson(collection);
	}

	/**
	 * Parses a JSON object.
	 * 
	 * @param data
	 * @return
	 * @throws ParserException
	 */
	private JSONObject parseJSONObject(String data) throws ParserException {
		JSONParser jsonParser = new JSONParser();

		Object obj;
		try {
			obj = jsonParser.parse(data);
		} catch (ParseException e) {
			String message = Messages.getString("ODataJSONParser.1"); //$NON-NLS-1$
			LOGGER.warning(message);
			throw new ParserException(message, e);
		}

		JSONObject jsonObject = (JSONObject) obj;
		return jsonObject;
	}

	/**
	 * Converts the given collection to an ODataCollectionJson object.
	 * 
	 * @param collection
	 * @return - the converted object.
	 */
	private ODataCollection convertToODataCollectionJson(
			LinkedList<ODataEntry> collection) {
		ODataCollectionJson odataCollection = new ODataCollectionJson();
		ODataEntryJson[] entries = new ODataEntryJson[collection.size()];
		odataCollection.setEntries(collection.toArray(entries));
		return odataCollection;
	}

	@Override
	public ODataProperty parseODataProperty(String data) throws ParserException {
		ODataPropertyJson dataProperty = new ODataPropertyJson();
		JSONObject jsonObject = parseJSONObject(data);

		JSONObject obj2 = (JSONObject) jsonObject.get(ODataJsonTags.D_TAG);

		if (obj2 != null) {
			Map<?, ?> results = (HashMap<?, ?>) obj2
					.get(ODataJsonTags.RESULTS_TAG);
			if (results != null) {
				return parseProperty(dataProperty, results);
			} else {
				Set<?> keySet = obj2.keySet();
				if (keySet.size() == 1) {
					Object object = obj2.get(keySet.iterator().next());
					return parseProperty(dataProperty, (Map<?, ?>) object);
				} else {
					return parseProperty(dataProperty, obj2);
				}
			}
		} else {
			return parseProperty(dataProperty, jsonObject);
		}
	}

	/**
	 * Parses a property.
	 * 
	 * @param property
	 * @param properties
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private ODataProperty parseProperty(ODataPropertyJson property,
			Map<?, ?> properties) {
		Set<String> keySet = (Set<String>) properties.keySet();

		if (keySet.size() == 1) {
			String key = keySet.iterator().next();
			Object value = properties.get(key);
			return primitivePropertyInitialization(property, key, value);
		}

		for (String key : keySet) {
			Object value = properties.get(key);
			if (key.equalsIgnoreCase(ODataJsonTags.METADATA_TAG)) {
				addMetadata(property, properties);
			} else {
				addChildProperty(property, key, value);
			}
		}
		return property;
	}

	/**
	 * Add child property to the given property initialized with the given key
	 * and value.
	 * 
	 * @param dataProperty
	 * @param key
	 * @param value
	 */
	private void addChildProperty(ODataPropertyJson dataProperty, String key,
			Object value) {
		ODataPropertyJson childDataProperty = new ODataPropertyJson();
		childDataProperty.setName(key);
		childDataProperty.setValue(value.toString());
		dataProperty.putChildProperty(childDataProperty);
	}

	/**
	 * Add metadata to the given property.
	 * 
	 * @param dataProperty
	 * @param properties
	 */
	private void addMetadata(ODataPropertyJson dataProperty,
			Map<?, ?> properties) {
		JSONObject metadata = (JSONObject) properties
				.get(ODataJsonTags.METADATA_TAG);
		dataProperty.setMetadataType(metadata.get(ODataJsonTags.TYPE_TAG)
				.toString());
		dataProperty.setName(metadata.get(ODataJsonTags.TYPE_TAG).toString());
	}

	/**
	 * Initializes the given property with the given key and value.
	 * 
	 * @param dataProperty
	 * @param key
	 * @param value
	 * @return - the property initialized.
	 */
	private ODataProperty primitivePropertyInitialization(
			ODataPropertyJson dataProperty, String key, Object value) {
		dataProperty.setName(key);
		dataProperty.setValue(value.toString());
		return dataProperty;
	}

	@SuppressWarnings("unchecked")
	@Override
	public ServiceDocument parseServiceDocument(String data)
			throws ParserException {
		JSONObject jsonObject = parseJSONObject(data);

		// The name of the name/value pair is always "d" and the value is the
		// JSON representation of an OData resource.
		JSONObject obj2 = (JSONObject) jsonObject.get(ODataJsonTags.D_TAG);

		// Service Documents are represented in JSON by an object with a single
		// name/value pair with the name equal to "EntitySets" and the value
		// being an array of Collection names.
		List<String> entitySets = (ArrayList<String>) obj2.get(ENTITY_SETS_KEY);

		// Initializing the ServiceDocument
		ServiceDocument document = new ServiceDocumentJson();
		String[] entitySetsArray = new String[entitySets.size()];
		document.setCollections(entitySets.toArray(entitySetsArray));

		return document;
	}

	@Override
	public String format(ODataEntry entry) throws MarshalerException {
		// using our implementation of 'toJSONString()' method
		String jsonText = ((ODataEntryJson) entry).toJSONString();

		return jsonText;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public String format(ODataCollection collection) throws MarshalerException {
		// using LinkedHashMap so it will keep the order
		Map root = new LinkedHashMap();
		// representing the results as a JSON array (java.util.List)
		JSONArray results = new JSONArray();

		ODataEntry[] entries = collection.getEntries();
		// going over all the entries and adding them to the 'results'
		for (ODataEntry oDataEntry : entries) {
			results.add(oDataEntry);
		}

		// adding the results to 'd'
		root.put(ODataJsonTags.RESULTS_TAG, results);

		// convert the json object to a string
		// each child object calls its 'toJSONString' method
		String jsonText = JSONValue.toJSONString(root);

		return jsonText;
	}

	@Override
	public TypeConverter getTypeConverter() {
		return typeConverter;
	}

	@Override
	public Representation getRepresentation() {
		return Representation.JSON;
	}

	@Override
	public String format(Edmx edmx) throws MarshalerException {
		return Marshaller.getInstance().format(edmx);
	}

	@Override
	public ComplexTypeCollection parseComplexTypeCollection(String xml,
			String serviceOperationName) throws ParserException {
		ODataCollection parseODataCollection = ODataParserFactory
				.createInstance(Representation.JSON).parseODataCollection(xml);
		ComplexTypeCollection result = new ComplexTypeCollection(
				serviceOperationName);
		result.setName(serviceOperationName);
		ODataPropertyJson[] elements = new ODataPropertyJson[parseODataCollection
				.getEntries().length];
		int i = 0;
		for (ODataEntry entry : parseODataCollection.getEntries()) {
			ODataPropertyJson property = new ODataPropertyJson();
			property.setName("d:element");
			ODataProperty[] properties = entry.getProperties();
			for (ODataProperty oDataProperty : properties) {
				property.putChildProperty(oDataProperty);
			}
			elements[i] = property;
			i++;
		}

		result.setElements(elements);
		return result;
	}
}
