/*******************************************************************************
 *  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.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);
	}
}
