/*
 *                                                                            
 *  Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) 
 *                                                                            
 *  All rights reserved. This program and the accompanying materials           
 *  are made available under the terms of the Eclipse Public License 2.0        
 *  which accompanies this distribution, and is available at                  
 *  https://www.eclipse.org/legal/epl-2.0/                                 
 *                                 
 *  SPDX-License-Identifier: EPL-2.0                                 
 *                                                                            
 *  Contributors:                                                      
 * 	   Florian Pirchner - Initial implementation
 *     Loetz GmbH&Co.KG                               
 * 
 */

package org.eclipse.osbp.vaadin.emf.data;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.xtext.common.types.JvmAnnotationReference;
import org.eclipse.xtext.common.types.JvmAnnotationType;
import org.eclipse.xtext.common.types.JvmDeclaredType;
import org.eclipse.xtext.common.types.JvmFeature;
import org.eclipse.xtext.common.types.JvmField;
import org.eclipse.xtext.common.types.JvmOperation;
import org.eclipse.xtext.common.types.JvmParameterizedTypeReference;
import org.eclipse.xtext.common.types.JvmPrimitiveType;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmVisibility;
import org.eclipse.xtext.common.types.util.RawSuperTypes;
import org.eclipse.xtext.xbase.lib.StringExtensions;

// TODO: Auto-generated Javadoc
/**
 * Helper class to collect all properties for a given JvmType.
 */
@SuppressWarnings("restriction")
public class JvmTypeProperties {

	/**
	 * Normalizes the method name.
	 *
	 * @param simpleName
	 *            the simple name
	 * @return the string
	 */
	public static String toPropertyName(String simpleName) {
		if (simpleName == null) {
			return null;
		}
		String tempName = null;
		if (isSetter(simpleName)) {
			tempName = StringExtensions.toFirstLower(simpleName.replaceFirst(
					"set", ""));
		} else if (isGetter(simpleName)) {
			if (simpleName.startsWith("get")) {
				tempName = StringExtensions.toFirstLower(simpleName
						.replaceFirst("get", ""));
			} else {
				tempName = StringExtensions.toFirstLower(simpleName
						.replaceFirst("is", ""));
			}
		}
		return tempName;
	}

	/**
	 * Checks if is getter.
	 *
	 * @param simpleName
	 *            the simple name
	 * @return true, if is getter
	 */
	public static boolean isGetter(String simpleName) {
		if (simpleName == null) {
			return false;
		}
		return simpleName.startsWith("get") || simpleName.startsWith("is");
	}

	/**
	 * Checks if is setter.
	 *
	 * @param simpleName
	 *            the simple name
	 * @return true, if is setter
	 */
	public static boolean isSetter(String simpleName) {
		return simpleName != null && simpleName.startsWith("set");
	}

	/**
	 * Calculates the operation infos for the given type.
	 *
	 * @param type
	 *            the type
	 * @return the operation infos
	 */
	public static Map<String, Info> getOperationInfos(JvmDeclaredType type) {
		return getOperationInfos(type, null);
	}

	/**
	 * Calculates the operation infos for the given info.
	 *
	 * @param root
	 *            the root
	 * @return the operation infos
	 */
	public static Map<String, Info> getOperationInfos(Info root) {

		JvmType type = null;
		if (root.isMany()) {
			type = root.getParameterizedType();
		} else {
			type = root.getType();
		}

		Map<String, Info> result = null;
		if (type instanceof JvmDeclaredType) {
			result = getOperationInfos((JvmDeclaredType) type);
		} else {
			result = new HashMap<String, JvmTypeProperties.Info>();
		}
		// apply the info as a parent
		for (Info temp : result.values()) {
			temp.setParent(root);
		}

		return result;
	}

	/**
	 * Calculates the operation infos for the given type.
	 *
	 * @param type
	 *            the type
	 * @param filterName
	 *            - is used to filter only methods property names matching the
	 *            filter name.
	 * @return the operation infos
	 */
	public static Map<String, Info> getOperationInfos(JvmDeclaredType type,
			String filterName) {
		Map<String, Info> infos = new HashMap<String, Info>();
		for (JvmFeature feature : type.getAllFeatures()) {
			if (!(feature instanceof JvmOperation)) {
				continue;
			}

			JvmOperation operation = (JvmOperation) feature;
			if (operation.getVisibility() != JvmVisibility.PUBLIC) {
				continue;
			}

			if (!isSetter(operation.getSimpleName())
					&& operation.getParameters().size() > 1) {
				continue;
			}

			String propertyName = toPropertyName(operation.getSimpleName());
			if (propertyName == null) {
				continue;
			}

			if (filterName != null && !filterName.equals(propertyName)) {
				continue;
			}

			if (operation.getSimpleName().equals("getClass")) {
				continue;
			}

			if (!isGetter(operation.getSimpleName())
					&& !isSetter(operation.getSimpleName())) {
				continue;
			}

			String id = calcId(operation.getDeclaringType(),
					operation.getSimpleName());
			if (!infos.containsKey(id)) {
				Info info = new Info();
				info.id = id;
				info.name = propertyName;
				infos.put(id, info);
			}

			Info info = infos.get(id);
			if (isGetter(operation.getSimpleName())) {
				info.getter = operation;
			} else {
				if (!propertyName.equals("dirty")) {
					info.setter = operation;
				}
			}
		}

		// apply readonly and create descriptions
		for (Info info : infos.values()) {
			if (info.getter == null) {
				continue;
			}
			if (info.setter == null) {
				info.readonly = true;
			}

			// TODO Pirchner - remove this workaround
			if (info.name.equals("id") || info.name.equals("uuid")) {
				info.idProperty = true;
			}
		}

		for (JvmFeature member : type.getAllFeatures()) {
			if (member instanceof JvmField) {
				JvmField field = (JvmField) member;
				String id = calcFieldId(field.getDeclaringType(),
						field.getSimpleName());
				if (infos.containsKey(id)) {
					Info info = infos.get(id);
					info.setField(field);
					info.type = field.getType().getType();
					info.primitive = info.type instanceof JvmPrimitiveType
							|| info.type.getQualifiedName().equals(
									String.class.getName());

					// collect all super types and check if collection is part
					// of them
					Set<String> superTypes = new RawSuperTypes()
							.collectNames(info.type);
					for (String typeName : superTypes) {
						if (typeName.equals(Collection.class.getName())) {
							info.many = true;
							break;
						}
					}

					if (info.many) {
						JvmParameterizedTypeReference typeRef = (JvmParameterizedTypeReference) field
								.getType();
						if (!typeRef.getArguments().isEmpty()) {
							info.parameterizedType = typeRef.getArguments()
									.get(0).getType();
						}
					}
				}
			}
		}
		return infos;
	}

	/**
	 * Normalizes the name.
	 *
	 * @param declaringType
	 *            the declaring type
	 * @param simpleName
	 *            the simple name
	 * @return the string
	 */
	public static String calcId(JvmDeclaredType declaringType, String simpleName) {
		String tempName = toPropertyName(simpleName);
		if (tempName == null) {
			return null;
		}

		return declaringType.getQualifiedName() + ":" + tempName;
	}

	/**
	 * Normalizes the name.
	 *
	 * @param declaringType
	 *            the declaring type
	 * @param simpleName
	 *            the simple name
	 * @return the string
	 */
	public static String calcFieldId(JvmDeclaredType declaringType,
			String simpleName) {
		return declaringType.getQualifiedName() + ":" + simpleName;
	}

	/**
	 * The Class Info.
	 */
	public static class Info implements Comparable<Info> {

		/**
		 * Can by any object that requested the info. For instance a YBeanSlot,
		 * an Entity, a JvmField,... The root should only be set for the top
		 * most parent.
		 */
		private Object root;
		/**
		 * The parent which requested this instance of info.
		 */
		private Info parent;

		/** The id. */
		private String id;

		/** The name. */
		private String name;

		/** The readonly. */
		private boolean readonly;

		/** The primitive. */
		private boolean primitive;

		/** The getter. */
		private JvmOperation getter;

		/** The setter. */
		private JvmOperation setter;

		/** The field. */
		private JvmField field;

		/** The type. */
		private JvmType type;

		/** The parameterized type. */
		private JvmType parameterizedType;

		/** The many. */
		private boolean many;

		/** The id property. */
		private boolean idProperty;

		/** The children. */
		private List<Info> children = new ArrayList<>();

		/**
		 * Gets the parent which requested this instance of info.
		 *
		 * @return the parent which requested this instance of info
		 */
		public Info getParent() {
			return parent;
		}

		/**
		 * Gets the children.
		 *
		 * @return the children
		 */
		public List<Info> getChildren() {
			return children;
		}

		/**
		 * Adds the child info.
		 *
		 * @param temp
		 *            the temp
		 */
		public void addChildInfo(Info temp) {
			children.add(temp);
		}

		/**
		 * Sets the parent which requested this instance of info.
		 *
		 * @param parent
		 *            the new parent which requested this instance of info
		 */
		public void setParent(Info parent) {
			this.parent = parent;
			parent.addChildInfo(this);
		}

		/**
		 * Gets the top parent.
		 *
		 * @return the top parent
		 */
		public Info getTopParent() {
			if (getParent() != null) {
				return getParent().getTopParent();
			}
			return this;
		}

		/**
		 * Gets the can by any object that requested the info.
		 *
		 * @return the can by any object that requested the info
		 */
		public Object getRoot() {
			if (this.root == null && getParent() != null) {
				return getParent().getRoot();
			}
			return root;
		}

		/**
		 * Sets the can by any object that requested the info.
		 *
		 * @param root
		 *            the new can by any object that requested the info
		 */
		public void setRoot(Object root) {
			this.root = root;
		}

		/**
		 * Gets the id.
		 *
		 * @return the id
		 */
		public String getId() {
			return id;
		}

		/**
		 * Sets the id.
		 *
		 * @param id
		 *            the new id
		 */
		public void setId(String id) {
			this.id = id;
		}

		/**
		 * Gets the name.
		 *
		 * @return the name
		 */
		public String getName() {
			return name;
		}

		/**
		 * Sets the name.
		 *
		 * @param name
		 *            the new name
		 */
		public void setName(String name) {
			this.name = name;
		}

		/**
		 * Checks if is readonly.
		 *
		 * @return true, if is readonly
		 */
		public boolean isReadonly() {
			return readonly;
		}

		/**
		 * Sets the readonly.
		 *
		 * @param readonly
		 *            the new readonly
		 */
		public void setReadonly(boolean readonly) {
			this.readonly = readonly;
		}

		/**
		 * Gets the getter.
		 *
		 * @return the getter
		 */
		public JvmOperation getGetter() {
			return getter;
		}

		/**
		 * Sets the getter.
		 *
		 * @param getter
		 *            the new getter
		 */
		public void setGetter(JvmOperation getter) {
			this.getter = getter;
		}

		/**
		 * Gets the setter.
		 *
		 * @return the setter
		 */
		public JvmOperation getSetter() {
			return setter;
		}

		/**
		 * Sets the setter.
		 *
		 * @param setter
		 *            the new setter
		 */
		public void setSetter(JvmOperation setter) {
			this.setter = setter;
		}

		/**
		 * Gets the field.
		 *
		 * @return the field
		 */
		public JvmField getField() {
			return field;
		}

		/**
		 * The jvm type containing the field.
		 *
		 * @return the declaring type
		 */
		public JvmDeclaredType getDeclaringType() {
			return field.getDeclaringType();
		}

		/**
		 * Sets the field.
		 *
		 * @param field
		 *            the new field
		 */
		public void setField(JvmField field) {
			this.field = field;
		}

		/**
		 * Checks if is primitive.
		 *
		 * @return true, if is primitive
		 */
		public boolean isPrimitive() {
			return primitive;
		}

		/**
		 * Sets the primitive.
		 *
		 * @param primitive
		 *            the new primitive
		 */
		public void setPrimitive(boolean primitive) {
			this.primitive = primitive;
		}

		/**
		 * Gets the type.
		 *
		 * @return the type
		 */
		public JvmType getType() {
			return type;
		}

		/**
		 * Sets the type.
		 *
		 * @param type
		 *            the new type
		 */
		public void setType(JvmType type) {
			this.type = type;
		}

		/**
		 * Checks if is many.
		 *
		 * @return true, if is many
		 */
		public boolean isMany() {
			return many;
		}

		/**
		 * Checks if is id property.
		 *
		 * @return true, if is id property
		 */
		public boolean isIdProperty() {
			return idProperty;
		}

		/**
		 * Sets the many.
		 *
		 * @param many
		 *            the new many
		 */
		public void setMany(boolean many) {
			this.many = many;
		}

		/**
		 * Gets the parameterized type.
		 *
		 * @return the parameterized type
		 */
		public JvmType getParameterizedType() {
			return parameterizedType;
		}

		/**
		 * Sets the parameterized type.
		 *
		 * @param parameterizedType
		 *            the new parameterized type
		 */
		public void setParameterizedType(JvmType parameterizedType) {
			this.parameterizedType = parameterizedType;
		}

		/**
		 * Returns true, if the info has an annotation matching the given
		 * annotationType.
		 *
		 * @param annotationType
		 *            the annotation type
		 * @return true, if successful
		 */
		public boolean hasAnnotation(Class<?> annotationType) {
			if (field == null) {
				return false;
			}
			for (JvmAnnotationReference annotation : field.getAnnotations()) {
				if (annotation.getAnnotation().getQualifiedName()
						.equals(annotationType.getName())) {
					return true;
				}
			}
			return false;
		}

		/**
		 * Returns the JvmAnnotationType instance or null.
		 *
		 * @param annotationType
		 *            the annotation type
		 * @return true, if successful
		 */
		public JvmAnnotationType getAnnotation(Class<?> annotationType) {
			if (!hasAnnotation(annotationType)) {
				return null;
			}
			for (JvmAnnotationReference annotation : field.getAnnotations()) {
				if (annotation.getAnnotation().getQualifiedName()
						.equals(annotationType.getName())) {
					return annotation.getAnnotation();
				}
			}
			return null;
		}

		/**
		 * Returns the dot'ed attribute path for this info and its parents. For
		 * instance <code>person.address.name</code>.
		 *
		 * @return the attribute path
		 */
		public String getAttributePath() {
			return getAttributePath(parent, name);
		}

		/**
		 * Gets the attribute path.
		 *
		 * @param parent
		 *            the parent
		 * @param postFix
		 *            the post fix
		 * @return the attribute path
		 */
		protected String getAttributePath(Info parent, String postFix) {
			if (parent != null) {
				String temp = parent.getAttributePath();
				return temp + "." + postFix;
			} else {
				return postFix;
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.Comparable#compareTo(java.lang.Object)
		 */
		@Override
		public int compareTo(Info other) {
			if (name == null || other == null) {
				return -1;
			}
			return name.compareTo(other.getName());
		}
	}
}
