/**
 * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), 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 v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *         Florian Pirchner - Initial implementation
 */
package org.eclipse.osbp.runtime.common.annotations;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.reflect.MethodUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The Class DtoUtils.
 */
public class DtoUtils {

	/** The Constant LOGGER. */
	private static final Logger LOGGER = LoggerFactory.getLogger(DtoUtils.class);

	/** The infos. */
	private static Map<Class<?>, Info> INFOS = Collections.synchronizedMap(new HashMap<Class<?>, DtoUtils.Info>());

	/**
	 * Returns the dispose field. Field annotated with {@link Dispose}.
	 *
	 * @param clazz
	 *            the clazz
	 * @return the dispose field
	 */
	public static Field getDisposeField(Class<?> clazz) {
		Info info = getInfo(clazz);
		return info.getDisposeField();
	}

	/**
	 * Returns the dispose field. Field annotated with {@link Dirty}.
	 *
	 * @param clazz
	 *            the clazz
	 * @return the dirty field
	 */
	public static Field getDirtyField(Class<?> clazz) {
		Info info = getInfo(clazz);
		return info.getDirtyField();
	}

	/**
	 * Returns the domain key field. Field annotated with {@link DomainKey}.
	 *
	 * @param clazz
	 *            the clazz
	 * @return the domain key field
	 */
	public static Field getDomainKeyField(Class<?> clazz) {
		Info info = getInfo(clazz);
		return info.getDomainKeyField();
	}

	/**
	 * Returns the id field. Field annotated with {@link Id}.
	 *
	 * @param clazz
	 *            the clazz
	 * @return the id field
	 */
	public static Field getIdField(Class<?> clazz) {
		Info info = getInfo(clazz);
		return info.getIdField();
	}

	/**
	 * Returns the id key field. Field annotated with {@link Id}.
	 *
	 * @param instance
	 *            the instance
	 * @param idProperty
	 *            the id property
	 * @return the value
	 */
	public static Object getValue(Object instance, String idProperty) {
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(instance.getClass());
			for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
				if (pd.getName().equals(idProperty)) {
					Method idMethod = pd.getReadMethod();
					return idMethod.invoke(instance);
				}
			}
		} catch (Exception e) {
			LOGGER.error("{}", e);
		}
		return null;
	}

	/**
	 * Returns the domain description field. Field annotated with
	 * #DomainDescription.
	 *
	 * @param clazz
	 *            the clazz
	 * @return the domain description field
	 */
	public static Field getDomainDescriptionField(Class<?> clazz) {
		Info info = getInfo(clazz);
		return info.getDomainDescriptionField();
	}

	/**
	 * Returns the dispose field. Field annotated with {@link Dirty}.
	 *
	 * @param clazz
	 *            the clazz
	 * @return the dirty getter
	 */
	public static Method getDirtyGetter(Class<?> clazz) {
		Info info = getInfo(clazz);
		return info.getDirtyGetter();
	}

	/**
	 * Returns the dispose field. Field annotated with {@link Dirty}.
	 *
	 * @param clazz
	 *            the clazz
	 * @return the dirty setter
	 */
	public static Method getDirtySetter(Class<?> clazz) {
		Info info = getInfo(clazz);
		return info.getDirtySetter();
	}

	/**
	 * Returns the dispose method. Method annotated with {@link Dispose}.
	 *
	 * @param clazz
	 *            the clazz
	 * @return the dispose method
	 */
	public static Method getDisposeMethod(Class<?> clazz) {
		Info info = getInfo(clazz);
		return info.getDisposeMethod();
	}

	/**
	 * Returns true, if the given field is a dispose field.
	 *
	 * @param clazz
	 *            the clazz
	 * @param fieldName
	 *            the field name
	 * @return true, if is dispose field
	 */
	public static boolean isDisposeField(Class<?> clazz, String fieldName) {
		Info info = getInfo(clazz);
		return info.getDisposeField() != null ? info.getDisposeField().getName().equals(fieldName) : false;
	}

	/**
	 * Returns true, if the given field is a dirty field. Dirty fields indicate
	 * that the dto is dirty.
	 *
	 * @param clazz
	 *            the clazz
	 * @param fieldName
	 *            the field name
	 * @return true, if is dirty field
	 */
	public static boolean isDirtyField(Class<?> clazz, String fieldName) {
		Info info = getInfo(clazz);
		return info.getDirtyField() != null ? info.getDirtyField().getName().equals(fieldName) : false;
	}

	/**
	 * Returns true, if the given method is a dispose method.
	 *
	 * @param clazz
	 *            the clazz
	 * @param methodName
	 *            the method name
	 * @return true, if is dispose method
	 */
	public static boolean isDisposeMethod(Class<?> clazz, String methodName) {
		Info info = getInfo(clazz);
		return info.getDisposeField() != null ? info.getDisposeMethod().getName().equals(methodName) : false;
	}

	/**
	 * Tries to invoke the dispose method.
	 *
	 * @param obj
	 *            the obj
	 * @return true, if the method could be invoked. False otherwise.
	 */
	public static boolean invokeDisposeMethod(Object obj) {
		Info info = getInfo(obj.getClass());
		if (info != null && info.getDisposeMethod() != null) {
			try {
				info.getDisposeMethod().invoke(obj, new Object[0]);
			} catch (IllegalAccessException e) {
				return false;
			} catch (IllegalArgumentException e) {
				return false;
			} catch (InvocationTargetException e) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Tries to invoke the setDirty method.
	 *
	 * @param obj
	 *            the obj
	 * @param value
	 *            the value
	 * @return true, if the method could be invoked. False otherwise.
	 */
	public static boolean invokeDirtySetter(Object obj, boolean value) {
		Info info = getInfo(obj.getClass());
		if (info != null && info.getDirtySetter() != null) {
			try {
				info.getDirtySetter().invoke(obj, new Object[] { value });
			} catch (IllegalAccessException e) {
				return false;
			} catch (IllegalArgumentException e) {
				return false;
			} catch (InvocationTargetException e) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Tries to invoke the dirty getter. If there is no dirty getter available,
	 * the method throws an {@link IllegalAccessException}.
	 *
	 * @param obj
	 *            the obj
	 * @return true, if is dirty
	 * @throws IllegalAccessException
	 *             the illegal access exception
	 */
	public static boolean isDirty(Object obj) throws IllegalAccessException {
		return invokeDirtyGetter(obj);
	}

	/**
	 * Tries to invoke the isDirty method.
	 *
	 * @param obj
	 *            the obj
	 * @return true, if the method could be invoked. False otherwise.
	 * @throws IllegalAccessException
	 *             the illegal access exception
	 */
	public static boolean invokeDirtyGetter(Object obj) throws IllegalAccessException {
		Info info = getInfo(obj.getClass());
		if (info != null && info.getDirtySetter() != null) {
			try {
				return (Boolean) info.getDirtyGetter().invoke(obj, new Object[0]);
			} catch (IllegalAccessException e) {
			} catch (IllegalArgumentException e) {
			} catch (InvocationTargetException e) {
			}
		}
		throw new IllegalAccessException("Not a valid call");
	}

	/**
	 * Returns the info for the given class.
	 *
	 * @param clazz
	 *            the clazz
	 * @return the info
	 */
	protected static Info getInfo(Class<?> clazz) {
		Info info = INFOS.get(clazz);
		if (info == null) {
			info = createInfo(clazz);
		}
		return info;
	}

	/**
	 * Creates a new info.
	 *
	 * @param clazz
	 *            the clazz
	 * @return info
	 */
	private static Info createInfo(Class<?> clazz) {
		Info info = new Info();
		applyFieldInfo(clazz, info);
		applyMethodInfo(clazz, info);

		INFOS.put(clazz, info);

		return info;
	}

	/**
	 * Returns the adapter which has proper type from the given dto. Or
	 * <code>null</code> if no adapter is available.
	 *
	 * @param <A>
	 *            the generic type
	 * @param type
	 *            the type
	 * @param dto
	 *            the dto
	 * @return the adapter
	 */
	@SuppressWarnings("unchecked")
	public static <A> A getAdapter(Class<A> type, Object dto) {
		if (type == null || dto == null) {
			return null;
		}
		Info info = getInfo(dto.getClass());
		if (info.getPropertyChangeSupportField() == null) {
			return null;
		}

		try {
			info.getPropertyChangeSupportField().setAccessible(true);
			PropertyChangeSupport changeSupport = (PropertyChangeSupport) info.getPropertyChangeSupportField().get(dto);
			if (changeSupport == null) {
				return null;
			}

			for (PropertyChangeListener listener : changeSupport.getPropertyChangeListeners()) {
				if (type.isAssignableFrom(listener.getClass())) {
					return (A) listener;
				}
			}
		} catch (IllegalArgumentException e) {
			LOGGER.error("{}", e);
		} catch (IllegalAccessException e) {
			LOGGER.error("{}", e);
		}
		return null;
	}

	/**
	 * Registers the adapter as a property changed listener.
	 *
	 * @param adapter
	 *            the adapter
	 * @param dto
	 *            the dto
	 */
	public static void registerAdapter(PropertyChangeListener adapter, Object dto) {
		if (adapter == null || dto == null) {
			return;
		}

		try {
			MethodUtils.invokeMethod(dto, "addPropertyChangeListener", adapter);
		} catch (SecurityException e) {
			LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName());
		} catch (IllegalAccessException e) {
			LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName());
		} catch (IllegalArgumentException e) {
			LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName());
		} catch (InvocationTargetException e) {
			LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName());
		} catch (NoSuchMethodException e) {
			LOGGER.info("Observer for dirtyState handling could not be added for " + dto.getClass().getName());
		}
	}

	/**
	 * Applies all required field infos to the info object.
	 *
	 * @param clazz
	 *            the clazz
	 * @param info
	 *            the info
	 */
	private static void applyFieldInfo(Class<?> clazz, Info info) {
		try {
			for (Field field : clazz.getDeclaredFields()) {
				if (field.getAnnotation(Dispose.class) != null) {
					info.disposeField = field;
				}
				if (field.getAnnotation(DomainKey.class) != null) {
					info.domainKeyField = field;
				}
				if (field.getAnnotation(DomainDescription.class) != null) {
					info.domainDescriptionField = field;
				}
				if (field.getAnnotation(Id.class) != null) {
					info.idField = field;
				}

				if (field.getType() == PropertyChangeSupport.class) {
					info.propertyChangeSupportField = field;
				}

				if (field.getAnnotation(Dirty.class) != null) {
					info.dirtyField = field;

					try {
						BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
						for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
							if (pd.getName().equals(info.dirtyField.getName())) {
								info.dirtyPropertyDescriptor = pd;
								break;
							}
						}
					} catch (IntrospectionException e) {
						LOGGER.error("{}", e);
					}
				}
				if (info.disposeField != null && info.dirtyField != null && info.domainKeyField != null
						&& info.domainDescriptionField != null && info.idField != null) {
					break;
				}
			}

			if (info.disposeField == null || info.domainKeyField == null || info.domainDescriptionField == null
					|| info.idField == null) {
				Class<?> superClass = clazz.getSuperclass();
				if (superClass != null) {
					applyFieldInfo(superClass, info);
				}
			}
		} catch (SecurityException e) {
			LOGGER.error("{}", e);
		}
	}

	/**
	 * Applies all required field infos to the info object.
	 *
	 * @param clazz
	 *            the clazz
	 * @param info
	 *            the info
	 */
	private static void applyMethodInfo(Class<?> clazz, Info info) {
		try {
			for (Method method : clazz.getDeclaredMethods()) {
				if (method.getAnnotation(Dispose.class) != null) {
					info.disposeMethod = method;
					break;
				}
			}

			if (info.disposeMethod == null) {
				Class<?> superClass = clazz.getSuperclass();
				if (superClass != null) {
					applyMethodInfo(superClass, info);
				}
			}
		} catch (SecurityException e) {
			LOGGER.error("{}", e);
		}
	}

	/**
	 * Find field.
	 *
	 * @param clazz
	 *            the clazz
	 * @param name
	 *            the name
	 * @return the field
	 */
	protected Field findField(Class<?> clazz, String name) {
		try {
			Field field = clazz.getDeclaredField(name);
			return field;
		} catch (NoSuchFieldException e) {
			Class<?> superClass = clazz.getSuperclass();
			if (superClass != null) {
				return findField(superClass, name);
			}
		} catch (SecurityException e) {
			LOGGER.error("{}", e);
		}
		return null;
	}

	/**
	 * The Class Info.
	 */
	private static class Info {

		/** The property change support field. */
		private Field propertyChangeSupportField;

		/** The dispose field. */
		private Field disposeField;

		/** The dispose method. */
		private Method disposeMethod;

		/** The id field. */
		private Field idField;

		/** The dirty field. */
		private Field dirtyField;

		/** The dirty property descriptor. */
		private PropertyDescriptor dirtyPropertyDescriptor;

		/** The domain key field. */
		private Field domainKeyField;

		/** The domain description field. */
		private Field domainDescriptionField;

		/**
		 * Gets the dispose field.
		 *
		 * @return the dispose field
		 */
		public Field getDisposeField() {
			return disposeField;
		}

		/**
		 * Gets the dirty field.
		 *
		 * @return the dirty field
		 */
		public Field getDirtyField() {
			return dirtyField;
		}

		/**
		 * Gets the dirty getter.
		 *
		 * @return the dirty getter
		 */
		public Method getDirtyGetter() {
			return dirtyPropertyDescriptor != null ? dirtyPropertyDescriptor.getReadMethod() : null;
		}

		/**
		 * Gets the dirty setter.
		 *
		 * @return the dirty setter
		 */
		public Method getDirtySetter() {
			return dirtyPropertyDescriptor != null ? dirtyPropertyDescriptor.getWriteMethod() : null;
		}

		/**
		 * Gets the dispose method.
		 *
		 * @return the dispose method
		 */
		public Method getDisposeMethod() {
			return disposeMethod;
		}

		/**
		 * Gets the domain key field.
		 *
		 * @return the domain key field
		 */
		public Field getDomainKeyField() {
			return domainKeyField;
		}

		/**
		 * Gets the domain description field.
		 *
		 * @return the domain description field
		 */
		public Field getDomainDescriptionField() {
			return domainDescriptionField;
		}

		/**
		 * Gets the property change support field.
		 *
		 * @return the property change support field
		 */
		public Field getPropertyChangeSupportField() {
			return propertyChangeSupportField;
		}

		public Field getIdField() {
			return idField;
		}

	}

}
