/*******************************************************************************
 * Copyright (c) 2007, 2012 Oracle. 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:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.common.core.internal.resource.java.source;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jpt.common.core.internal.utility.jdt.ASTTools;
import org.eclipse.jpt.common.core.internal.utility.jdt.JDTType;
import org.eclipse.jpt.common.core.resource.java.JavaResourceCompilationUnit;
import org.eclipse.jpt.common.core.resource.java.JavaResourceEnum;
import org.eclipse.jpt.common.core.resource.java.JavaResourceField;
import org.eclipse.jpt.common.core.resource.java.JavaResourceMethod;
import org.eclipse.jpt.common.core.resource.java.JavaResourceType;
import org.eclipse.jpt.common.core.utility.jdt.Type;
import org.eclipse.jpt.common.utility.MethodSignature;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable;
import org.eclipse.jpt.common.utility.internal.iterables.TreeIterable;

/**
 * Java source type (type or interface)
 */
final class SourceType
	extends SourceAbstractType<Type>
	implements JavaResourceType
{

	private String superclassQualifiedName;

	private boolean abstract_;  // 'abstract' is a reserved word

	private boolean hasNoArgConstructor;

	private boolean hasPrivateNoArgConstructor;

	private final Vector<JavaResourceType> types;

	private final Vector<JavaResourceEnum> enums;

	private final Vector<JavaResourceField> fields;

	private final Vector<JavaResourceMethod> methods;


	// ********** construction/initialization **********

	/**
	 * build top-level type
	 */
	static JavaResourceType newInstance(
			JavaResourceCompilationUnit javaResourceCompilationUnit,
			TypeDeclaration typeDeclaration,
			CompilationUnit astRoot) {
		Type type = new JDTType(
				typeDeclaration,
				javaResourceCompilationUnit.getCompilationUnit(),
				javaResourceCompilationUnit.getModifySharedDocumentCommandExecutor(),
				javaResourceCompilationUnit.getAnnotationEditFormatter());
		JavaResourceType jrpt = new SourceType(javaResourceCompilationUnit, type);
		jrpt.initialize(astRoot);
		return jrpt;
	}

	/**
	 * build nested type
	 */
	private static JavaResourceType newInstance(
			JavaResourceCompilationUnit javaResourceCompilationUnit,
			Type declaringType,
			TypeDeclaration typeDeclaration,
			int occurrence,
			CompilationUnit astRoot) {
		Type type = new JDTType(
				declaringType,
				typeDeclaration,
				occurrence,
				javaResourceCompilationUnit.getCompilationUnit(),
				javaResourceCompilationUnit.getModifySharedDocumentCommandExecutor(),
				javaResourceCompilationUnit.getAnnotationEditFormatter());
		JavaResourceType jrpt = new SourceType(javaResourceCompilationUnit, type);
		jrpt.initialize(astRoot);
		return jrpt;
	}

	private SourceType(JavaResourceCompilationUnit javaResourceCompilationUnit, Type type) {
		super(javaResourceCompilationUnit, type);
		this.types = new Vector<JavaResourceType>();
		this.enums = new Vector<JavaResourceEnum>();
		this.fields = new Vector<JavaResourceField>();
		this.methods = new Vector<JavaResourceMethod>();
	}

	@Override
	public void initialize(CompilationUnit astRoot) {
		super.initialize(astRoot);
		ITypeBinding binding = this.annotatedElement.getBinding(astRoot);
		this.superclassQualifiedName = this.buildSuperclassQualifiedName(binding);
		this.abstract_ = this.buildAbstract(binding);
		this.hasNoArgConstructor = this.buildHasNoArgConstructor(binding);
		this.hasPrivateNoArgConstructor = this.buildHasPrivateNoArgConstructor(binding);
		this.initializeTypes(astRoot);
		this.initializeEnums(astRoot);
		this.initializeFields(astRoot);
		this.initializeMethods(astRoot);
	}


	// ********** update **********

	@Override
	public void synchronizeWith(CompilationUnit astRoot) {
		super.synchronizeWith(astRoot);
		ITypeBinding binding = this.annotatedElement.getBinding(astRoot);
		this.syncSuperclassQualifiedName(this.buildSuperclassQualifiedName(binding));
		this.syncAbstract(this.buildAbstract(binding));
		this.syncHasNoArgConstructor(this.buildHasNoArgConstructor(binding));
		this.syncHasPrivateNoArgConstructor(this.buildHasPrivateNoArgConstructor(binding));
		this.syncTypes(astRoot);
		this.syncEnums(astRoot);
		this.syncFields(astRoot);
		this.syncMethods(astRoot);
	}


	// ********** SourceAnnotatedElement implementation **********

	@Override
	public void resolveTypes(CompilationUnit astRoot) {
		super.resolveTypes(astRoot);

		this.syncSuperclassQualifiedName(this.buildSuperclassQualifiedName(this.annotatedElement.getBinding(astRoot)));

		for (JavaResourceField field : this.getFields()) {
			field.resolveTypes(astRoot);
		}

		// a new type can trigger a method parameter type to be a resolved,
		// fully-qualified name, so we need to rebuild our list of methods:
		//     "setFoo(Foo)" is not the same as "setFoo(com.bar.Foo)"
		// and, vice-versa, a removed type can "unresolve" a parameter type
		this.syncMethods(astRoot);

		for (JavaResourceMethod method : this.getMethods()) {
			method.resolveTypes(astRoot);
		}
		for (JavaResourceType type : this.getTypes()) {
			type.resolveTypes(astRoot);
		}
		for (JavaResourceEnum enum_ : this.getEnums()) {
			enum_.resolveTypes(astRoot);
		}
	}


	// ******** JavaResourceType implementation ********
	
	public Kind getKind() {
		return Kind.TYPE;
	}
	
	// ***** superclass qualified name
	public String getSuperclassQualifiedName() {
		return this.superclassQualifiedName;
	}

	private void syncSuperclassQualifiedName(String astSuperclassQualifiedName) {
		String old = this.superclassQualifiedName;
		this.superclassQualifiedName = astSuperclassQualifiedName;
		this.firePropertyChanged(SUPERCLASS_QUALIFIED_NAME_PROPERTY, old, astSuperclassQualifiedName);
	}

	private String buildSuperclassQualifiedName(ITypeBinding binding) {
		if (binding == null) {
			return null;
		}
		ITypeBinding superclass = binding.getSuperclass();
		return (superclass == null) ? null : superclass.getTypeDeclaration().getQualifiedName();
	}

	// ***** abstract
	public boolean isAbstract() {
		return this.abstract_;
	}

	private void syncAbstract(boolean astAbstract) {
		boolean old = this.abstract_;
		this.abstract_ = astAbstract;
		this.firePropertyChanged(ABSTRACT_PROPERTY, old, astAbstract);
	}

	private boolean buildAbstract(ITypeBinding binding) {
		return (binding == null) ? false : Modifier.isAbstract(binding.getModifiers());
	}

	// ***** no-arg constructor
	public boolean hasNoArgConstructor() {
		return this.hasNoArgConstructor;
	}

	private void syncHasNoArgConstructor(boolean astHasNoArgConstructor) {
		boolean old = this.hasNoArgConstructor;
		this.hasNoArgConstructor = astHasNoArgConstructor;
		this.firePropertyChanged(NO_ARG_CONSTRUCTOR_PROPERTY, old, astHasNoArgConstructor);
	}

	private boolean buildHasNoArgConstructor(ITypeBinding binding) {
		return (binding == null) ? false : typeHasNoArgConstructor(binding);
	}

	protected static boolean typeHasNoArgConstructor(ITypeBinding binding) {
		return findNoArgConstructor(binding) != null;
	}
	
	protected static IMethodBinding findNoArgConstructor(ITypeBinding binding) {
		for (IMethodBinding method : binding.getDeclaredMethods()) {
			if (method.isConstructor()) {
				if (method.getParameterTypes().length == 0) {
					return method;
				}
			}
		}
		return null;
	}

	// ***** private no-arg constructor
	public boolean hasPrivateNoArgConstructor() {
		return this.hasPrivateNoArgConstructor;
	}

	private void syncHasPrivateNoArgConstructor(boolean astHasPrivateNoArgConstructor) {
		boolean old = this.hasPrivateNoArgConstructor;
		this.hasPrivateNoArgConstructor = astHasPrivateNoArgConstructor;
		this.firePropertyChanged(PRIVATE_NO_ARG_CONSTRUCTOR_PROPERTY, old, astHasPrivateNoArgConstructor);
	}

	private boolean buildHasPrivateNoArgConstructor(ITypeBinding binding) {
		return (binding == null) ? false : typeHasPrivateNoArgConstructor(binding);
	}

	protected static boolean typeHasPrivateNoArgConstructor(ITypeBinding binding) {
		IMethodBinding method = findNoArgConstructor(binding);
		return (method != null) && Modifier.isPrivate(method.getModifiers());
	}
	
	
	// ***** public/protected no-arg constructor *****
	
	public boolean hasPublicOrProtectedNoArgConstructor() {
		Iterable<JavaResourceMethod> constructors = getConstructors();
		if (CollectionTools.size(constructors) == 0) {
			return true;
		}
		for (JavaResourceMethod constructor : constructors) {
			if (constructor.getParametersSize() == 0) {
				return Modifier.isPublic(constructor.getModifiers())
						|| Modifier.isProtected(constructor.getModifiers());
			}
		}
		return false;
	}
	
	public boolean hasPublicNoArgConstructor() {
		Iterable<JavaResourceMethod> constructors = this.getConstructors();
		if (CollectionTools.size(constructors) == 0) {
			return true;
		}
		for (JavaResourceMethod constructor : constructors) {
			if (constructor.getParametersSize() == 0) {
				return Modifier.isPublic(constructor.getModifiers());
			}
		}
		return false;
	}

	protected Iterable<JavaResourceMethod> getConstructors() {
		return new FilteringIterable<JavaResourceMethod>(this.getMethods()) {
			@Override
			protected boolean accept(JavaResourceMethod method) {
				return method.isConstructor();
			}
		};
	}
	

	// ********** types **********

	public Iterable<JavaResourceType> getTypes() {
		return new LiveCloneIterable<JavaResourceType>(this.types);  // read-only
	}

	public Iterable<JavaResourceType> getAllTypes() {
		return new TreeIterable<JavaResourceType>(this) {
			@Override
			protected Iterator<? extends JavaResourceType> children(JavaResourceType type) {
				return type.getTypes().iterator();
			}
		};
	}

	private JavaResourceType getType(String typeName, int occurrence) {
		for (JavaResourceType type : this.getTypes()) {
			if (type.isFor(typeName, occurrence)) {
				return type;
			}
		}
		return null;
	}

	private void addType(JavaResourceType type) {
		this.addItemToCollection(type, this.types, TYPES_COLLECTION);
	}

	private void removeTypes(Collection<JavaResourceType> remove) {
		this.removeItemsFromCollection(remove, this.types, TYPES_COLLECTION);
	}

	private void initializeTypes(CompilationUnit astRoot) {
		TypeDeclaration[] typeDeclarations = this.annotatedElement.getTypes(astRoot);
		CounterMap counters = new CounterMap(typeDeclarations.length);
		for (TypeDeclaration td : typeDeclarations) {
			String tdName = td.getName().getFullyQualifiedName();
			int occurrence = counters.increment(tdName);
			this.types.add(this.buildType(td, occurrence, astRoot));
		}
	}

	private void syncTypes(CompilationUnit astRoot) {
		TypeDeclaration[] typeDeclarations = this.annotatedElement.getTypes(astRoot);
		CounterMap counters = new CounterMap(typeDeclarations.length);
		HashSet<JavaResourceType> typesToRemove = new HashSet<JavaResourceType>(this.types);
		for (TypeDeclaration typeDeclaration : typeDeclarations) {
			String tdName = typeDeclaration.getName().getFullyQualifiedName();
			int occurrence = counters.increment(tdName);

			JavaResourceType type = this.getType(tdName, occurrence);
			if (type == null) {
				this.addType(this.buildType(typeDeclaration, occurrence, astRoot));
			} else {
				typesToRemove.remove(type);
				type.synchronizeWith(astRoot);
			}
		}
		this.removeTypes(typesToRemove);
	}

	private JavaResourceType buildType(TypeDeclaration nestedTypeDeclaration, int occurrence, CompilationUnit astRoot) {
		return newInstance(this.getJavaResourceCompilationUnit(), this.annotatedElement, nestedTypeDeclaration, occurrence, astRoot);
	}


	// ********** enums **********

	public Iterable<JavaResourceEnum> getEnums() {
		return new LiveCloneIterable<JavaResourceEnum>(this.enums);  // read-only
	}

	public Iterable<JavaResourceEnum> getAllEnums() {
		return this.getEnums();
	}

	private JavaResourceEnum getEnum(String enumName, int occurrence) {
		for (JavaResourceEnum enum_ : this.getEnums()) {
			if (enum_.isFor(enumName, occurrence)) {
				return enum_;
			}
		}
		return null;
	}

	private void addEnum(JavaResourceEnum enum_) {
		this.addItemToCollection(enum_, this.enums, ENUMS_COLLECTION);
	}

	private void removeEnums(Collection<JavaResourceEnum> remove) {
		this.removeItemsFromCollection(remove, this.enums, ENUMS_COLLECTION);
	}

	private void initializeEnums(CompilationUnit astRoot) {
		EnumDeclaration[] enumDeclarations = this.annotatedElement.getEnums(astRoot);
		CounterMap counters = new CounterMap(enumDeclarations.length);
		for (EnumDeclaration ed : enumDeclarations) {
			String tdName = ed.getName().getFullyQualifiedName();
			int occurrence = counters.increment(tdName);
			this.enums.add(this.buildEnum(ed, occurrence, astRoot));
		}
	}

	private void syncEnums(CompilationUnit astRoot) {
		EnumDeclaration[] enumDeclarations = this.annotatedElement.getEnums(astRoot);
		CounterMap counters = new CounterMap(enumDeclarations.length);
		HashSet<JavaResourceEnum> enumsToRemove = new HashSet<JavaResourceEnum>(this.enums);
		for (EnumDeclaration enumDeclaration : enumDeclarations) {
			String tdName = enumDeclaration.getName().getFullyQualifiedName();
			int occurrence = counters.increment(tdName);

			JavaResourceEnum enum_ = this.getEnum(tdName, occurrence);
			if (enum_ == null) {
				this.addEnum(this.buildEnum(enumDeclaration, occurrence, astRoot));
			} else {
				enumsToRemove.remove(enum_);
				enum_.synchronizeWith(astRoot);
			}
		}
		this.removeEnums(enumsToRemove);
	}

	private JavaResourceEnum buildEnum(EnumDeclaration nestedEnumDeclaration, int occurrence, CompilationUnit astRoot) {
		return SourceEnum.newInstance(this.getJavaResourceCompilationUnit(), this.annotatedElement, nestedEnumDeclaration, occurrence, astRoot);
	}


	// ********** fields **********

	public Iterable<JavaResourceField> getFields() {
		return new LiveCloneIterable<JavaResourceField>(this.fields);
	}

	private void addField(JavaResourceField field) {
		this.addItemToCollection(field, this.fields, FIELDS_COLLECTION);
	}

	private JavaResourceField getField(String fieldName, int occurrence) {
		for (JavaResourceField field : this.getFields()) {
			if (field.isFor(fieldName, occurrence)) {
				return field;
			}
		}
		return null;
	}

	private void removeFields(Collection<JavaResourceField> remove) {
		this.removeItemsFromCollection(remove, this.fields, FIELDS_COLLECTION);
	}

	private void initializeFields(CompilationUnit astRoot) {
		FieldDeclaration[] fieldDeclarations = this.annotatedElement.getFields(astRoot);
		CounterMap counters = new CounterMap(fieldDeclarations.length);
		for (FieldDeclaration fieldDeclaration : fieldDeclarations) {
			for (VariableDeclarationFragment fragment : fragments(fieldDeclaration)) {
				String fieldName = fragment.getName().getFullyQualifiedName();
				int occurrence = counters.increment(fieldName);
				this.fields.add(this.buildField(fieldName, occurrence, astRoot));
			}
		}
	}

	private void syncFields(CompilationUnit astRoot) {
		FieldDeclaration[] fieldDeclarations = this.annotatedElement.getFields(astRoot);
		CounterMap counters = new CounterMap(fieldDeclarations.length);
		HashSet<JavaResourceField> fieldsToRemove = new HashSet<JavaResourceField>(this.fields);
		for (FieldDeclaration fieldDeclaration : fieldDeclarations) {
			for (VariableDeclarationFragment fragment : fragments(fieldDeclaration)) {
				String fieldName = fragment.getName().getFullyQualifiedName();
				int occurrence = counters.increment(fieldName);

				JavaResourceField field = this.getField(fieldName, occurrence);
				if (field == null) {
					this.addField(this.buildField(fieldName, occurrence, astRoot));
				} else {
					fieldsToRemove.remove(field);
					field.synchronizeWith(astRoot);
				}
			}
		}
		this.removeFields(fieldsToRemove);
	}

	private JavaResourceField buildField(String fieldName, int occurrence, CompilationUnit astRoot) {
		return SourceField.newInstance(this, this.annotatedElement, fieldName, occurrence, this.getJavaResourceCompilationUnit(), astRoot);
	}

	// minimize scope of suppressed warnings
	@SuppressWarnings("unchecked")
	private static List<VariableDeclarationFragment> fragments(FieldDeclaration fd) {
		return fd.fragments();
	}


	// ********** methods **********

	public Iterable<JavaResourceMethod> getMethods() {
		return new LiveCloneIterable<JavaResourceMethod>(this.methods);
	}

	private JavaResourceMethod getMethod(MethodSignature signature, int occurrence) {
		for (JavaResourceMethod method : this.getMethods()) {
			if (method.isFor(signature, occurrence)) {
				return method;
			}
		}
		return null;
	}

	private void addMethod(JavaResourceMethod method) {
		this.addItemToCollection(method, this.methods, METHODS_COLLECTION);
	}

	private void removeMethods(Collection<JavaResourceMethod> remove) {
		this.removeItemsFromCollection(remove, this.methods, METHODS_COLLECTION);
	}

	private void initializeMethods(CompilationUnit astRoot) {
		MethodDeclaration[] methodDeclarations = this.annotatedElement.getMethods(astRoot);
		CounterMap counters = new CounterMap(methodDeclarations.length);
		for (MethodDeclaration methodDeclaration : methodDeclarations) {
			MethodSignature signature = ASTTools.buildMethodSignature(methodDeclaration);
			int occurrence = counters.increment(signature);
			this.methods.add(this.buildMethod(signature, occurrence, astRoot));
		}
	}

	private void syncMethods(CompilationUnit astRoot) {
		MethodDeclaration[] methodDeclarations = this.annotatedElement.getMethods(astRoot);
		CounterMap counters = new CounterMap(methodDeclarations.length);
		HashSet<JavaResourceMethod> methodsToRemove = new HashSet<JavaResourceMethod>(this.methods);
		for (MethodDeclaration methodDeclaration : methodDeclarations) {
			MethodSignature signature = ASTTools.buildMethodSignature(methodDeclaration);
			int occurrence = counters.increment(signature);

			JavaResourceMethod method = this.getMethod(signature, occurrence);
			if (method == null) {
				this.addMethod(this.buildMethod(signature, occurrence, astRoot));
			} else {
				methodsToRemove.remove(method);
				method.synchronizeWith(astRoot);
			}
		}
		this.removeMethods(methodsToRemove);
	}

	private JavaResourceMethod buildMethod(MethodSignature signature, int occurrence, CompilationUnit astRoot) {
		return SourceMethod.newInstance(this, this.annotatedElement, signature, occurrence, this.getJavaResourceCompilationUnit(), astRoot);
	}


	public boolean hasAnyAnnotatedFields() {
		for (JavaResourceField field : this.getFields()) {
			if (field.isAnnotated()) {
				return true;
			}
		}
		return false;
	}

	public boolean hasAnyAnnotatedMethods() {
		for (JavaResourceMethod method : this.getMethods()) {
			if (method.isAnnotated()) {
				return true;
			}
		}
		return false;
	}
	
	// Two more requirements for a valid equals() method:
	// 1. It should be public 
	// 2. The return type should be boolean
	// Both requirements are validated by the compiler so they are excluded here
	public boolean hasEqualsMethod() {
		for (JavaResourceMethod method : this.getMethods()) {
			if (StringTools.stringsAreEqual(method.getMethodName(), "equals") //$NON-NLS-1$
					&& method.getParametersSize() == 1
					&& StringTools.stringsAreEqual(method.getParameterTypeName(0), Object.class.getName())) {
				return true;
			}
		}
		return false;
	}
	
	// Two more requirements for a valid hashCode() method:
	// 1. It should be public 
	// 2. The return type should be int
	// Both requirements are validated by the compiler so they are excluded here
	public boolean hasHashCodeMethod() {
		for (JavaResourceMethod method : this.getMethods()) {
			if (StringTools.stringsAreEqual(method.getMethodName(), "hashCode") //$NON-NLS-1$
					&& method.getParametersSize() == 0) {
				return true;
			}
		}
		return false;
	}
	
	public JavaResourceMethod getMethod(String propertyName) {
		for (JavaResourceMethod method : this.getMethods()) {
			if (StringTools.stringsAreEqual(method.getMethodName(), propertyName)) {
				return method;
			}
		}
		return null;
	}
}
