/*******************************************************************************
 * Copyright (c) 2010, 2011 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.jaxb.core.internal.context;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.jpt.common.utility.internal.ClassName;
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.SnapshotCloneIterable;
import org.eclipse.jpt.common.utility.internal.iterables.SubIterableWrapper;
import org.eclipse.jpt.common.utility.internal.iterables.TransformationIterable;
import org.eclipse.jpt.jaxb.core.JaxbProject;
import org.eclipse.jpt.jaxb.core.context.JaxbClass;
import org.eclipse.jpt.jaxb.core.context.JaxbContextRoot;
import org.eclipse.jpt.jaxb.core.context.JaxbPackage;
import org.eclipse.jpt.jaxb.core.context.JaxbPersistentClass;
import org.eclipse.jpt.jaxb.core.context.JaxbPersistentEnum;
import org.eclipse.jpt.jaxb.core.context.JaxbRegistry;
import org.eclipse.jpt.jaxb.core.context.JaxbTransientClass;
import org.eclipse.jpt.jaxb.core.context.JaxbType;
import org.eclipse.jpt.jaxb.core.resource.java.JAXB;
import org.eclipse.jpt.jaxb.core.resource.java.JavaResourceAbstractType;
import org.eclipse.jpt.jaxb.core.resource.java.JavaResourceEnum;
import org.eclipse.jpt.jaxb.core.resource.java.JavaResourcePackage;
import org.eclipse.jpt.jaxb.core.resource.java.JavaResourceType;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;

/**
 * the context model root
 */
public class GenericContextRoot
		extends AbstractJaxbContextNode
		implements JaxbContextRoot {
	
	/* This object has no parent, so it must point to the JAXB project explicitly. */
	protected final JaxbProject jaxbProject;
	
	/* The map of package name to JaxbPackage objects */
	protected final Map<String, JaxbPackage> packages;
	
	/* The map of class name to JaxbType objects */
	protected final Map<String, JaxbType> types;
	
	
	public GenericContextRoot(JaxbProject jaxbProject) {
		super(null);  // the JAXB project is not really a "parent"...
		if (jaxbProject == null) {
			throw new NullPointerException();
		}
		this.jaxbProject = jaxbProject;
		this.packages = new HashMap<String, JaxbPackage>();
		this.types = new HashMap<String, JaxbType>();
		initialize();
	}
	
	
	@Override
	public JaxbContextRoot getContextRoot() {
		return this;
	}
	
	@Override
	protected boolean requiresParent() {
		return false;
	}
	
	protected void initialize() {
		// keep a master list of all types that we've processed so we don't process them again
		final Set<String> totalTypes = CollectionTools.<String>set();
		
		// keep an running list of types that we need to scan for further referenced types
		final Set<String> typesToScan = CollectionTools.<String>set();
		
		// process packages with annotations first
		for (String pkg : calculateInitialPackageNames()) {
			this.packages.put(pkg, buildPackage(pkg));
		}
		
		// process registry classes before other classes (they are completely determined by annotation)
		for (JavaResourceType registryResourceType : calculateRegistries()) {
			String className = registryResourceType.getQualifiedName();
			totalTypes.add(className);
			typesToScan.add(className);
			this.types.put(registryResourceType.getName(), buildRegistry(registryResourceType));
		}
		
		// calculate initial set of persistent types (annotated with @XmlType)
		final Set<JavaResourceAbstractType> resourceTypesToProcess = calculateInitialPersistentTypes();
		
		// while there are resource types to process or types to scan, continue to do so
		while (! resourceTypesToProcess.isEmpty() || ! typesToScan.isEmpty()) {
			for (JavaResourceAbstractType resourceType : new SnapshotCloneIterable<JavaResourceAbstractType>(resourceTypesToProcess)) {
				String className = resourceType.getQualifiedName();
				totalTypes.add(className);
				typesToScan.add(className);
				JaxbType.Kind jaxbTypeKind = calculateJaxbTypeKind(resourceType);
				this.types.put(resourceType.getName(), buildType(jaxbTypeKind, resourceType));
				resourceTypesToProcess.remove(resourceType);
			}
			
			for (String typeToScan : new SnapshotCloneIterable<String>(typesToScan)) {
				JaxbType jaxbType = getType(typeToScan);
				if (jaxbType != null) {
					for (String referencedTypeName : jaxbType.getDirectlyReferencedTypeNames()) {
						if (! totalTypes.contains(referencedTypeName)) {
							JavaResourceAbstractType referencedType = getJaxbProject().getJavaResourceType(referencedTypeName);
							if (referencedType != null) {
								resourceTypesToProcess.add(referencedType);
							}
						}
					}
				}
				typesToScan.remove(typeToScan);
			}
		}
		
		// once all classes have been processed, add packages
		for (String pkg : calculatePackageNames(totalTypes)) {
			if (! this.packages.containsKey(pkg)) {
				this.packages.put(pkg, buildPackage(pkg));
			}
		}
	}
	
	@Override
	public void synchronizeWithResourceModel() {
		super.synchronizeWithResourceModel();
		for (JaxbPackage each : getPackages()) {
			each.synchronizeWithResourceModel();
		}
		for (JaxbType each : getTypes()) {
			each.synchronizeWithResourceModel();
		}
	}
	
	@Override
	public void update() {
		super.update();
		
		// keep a master list of these so that objects are updated only once
		final Set<String> packagesToUpdate = CollectionTools.<String>set();
		final Set<String> typesToUpdate = CollectionTools.<String>set();
		
		// keep a (shrinking) running list of these so that we know which ones we do eventually need to remove
		final Set<String> packagesToRemove = CollectionTools.set(this.packages.keySet());
		final Set<String> typesToRemove = CollectionTools.set(this.types.keySet());
		
		// keep a master list of all types that we've processed so we don't process them again
		final Set<String> totalTypes = CollectionTools.<String>set();
		
		// keep an running list of types that we need to scan for further referenced types
		final Set<String> typesToScan = CollectionTools.<String>set();
		
		// process packages with annotations first
		for (String pkg : calculateInitialPackageNames()) {
			if (this.packages.containsKey(pkg)) {
				packagesToUpdate.add(pkg);
				packagesToRemove.remove(pkg);
			}
			else {
				this.addPackage(this.buildPackage(pkg));
			}
		}
		
		// process registry classes before other classes (they are completely determined by annotation)
		for (JavaResourceType registryResourceType : calculateRegistries()) {
			String className = registryResourceType.getQualifiedName();
			typesToRemove.remove(className);
			totalTypes.add(className);
			typesToScan.add(className);
			if (this.types.containsKey(className)) {
				if (this.types.get(className).getKind() == JaxbType.Kind.REGISTRY) {
					typesToUpdate.add(className);
				}
				else {
					this.removeType(className); // this will remove a type of another kind
					this.addType(buildRegistry(registryResourceType));
				}
			}
			else {
				this.addType(buildRegistry(registryResourceType));
			}
		}
		
		// calculate initial set of persistent types (annotated with @XmlType)
		final Set<JavaResourceAbstractType> resourceTypesToProcess = calculateInitialPersistentTypes();
		
		// while there are resource types to process or types to scan, continue to do so
		while (! resourceTypesToProcess.isEmpty() || ! typesToScan.isEmpty()) {
			for (JavaResourceAbstractType resourceType : new SnapshotCloneIterable<JavaResourceAbstractType>(resourceTypesToProcess)) {
				String className = resourceType.getQualifiedName();
				typesToRemove.remove(className);
				totalTypes.add(className);
				typesToScan.add(className);
				processType(resourceType, typesToUpdate);
				resourceTypesToProcess.remove(resourceType);
			}
			
			for (String typeToScan : new SnapshotCloneIterable<String>(typesToScan)) {
				JaxbType jaxbType = getType(typeToScan);
				if (jaxbType != null) {
					for (String referencedTypeName : jaxbType.getDirectlyReferencedTypeNames()) {
						if (! StringTools.stringIsEmpty(referencedTypeName) && ! totalTypes.contains(referencedTypeName)) {
							JavaResourceAbstractType referencedType = getJaxbProject().getJavaResourceType(referencedTypeName);
							if (referencedType != null) {
								resourceTypesToProcess.add(referencedType);
							}
						}
					}
				}
				typesToScan.remove(typeToScan);
			}
		}
		
		// once all classes have been processed, add packages
		for (String pkg : calculatePackageNames(totalTypes)) {
			if (this.packages.containsKey(pkg)) {
				packagesToUpdate.add(pkg);
				packagesToRemove.remove(pkg);
			}
			else {
				this.addPackage(this.buildPackage(pkg));
			}
		}
		
		for (String packageToUpdate : packagesToUpdate) {
			this.packages.get(packageToUpdate).update();
		}
		
		for (String typeToUpdate : typesToUpdate) {
			this.types.get(typeToUpdate).update();
		}
		
		for (String packageToRemove : packagesToRemove) {
			removePackage(packageToRemove);
		}
		
		for (String typeToRemove : typesToRemove) {
			removeType(typeToRemove);
		}
	}
	
	/**
	 * calculate set of packages that can be determined purely by presence of package annotations
	 */
	protected Set<String> calculateInitialPackageNames() {
		return CollectionTools.set(
				new TransformationIterable<JavaResourcePackage, String>(
						getJaxbProject().getAnnotatedJavaResourcePackages()) {
					@Override
					protected String transform(JavaResourcePackage o) {
						return o.getName();
					}
				});
	}
	
	/**
	 * calculate set of packages that can be determined from type names
	 */
	protected Set<String> calculatePackageNames(Set<String> typeNames) {
		Set<String> packageNames = CollectionTools.<String>set();
		for (String typeName : typeNames) {
			packageNames.add(ClassName.getPackageName(typeName));
		}
		return packageNames;
	}
	
	/*
	 * Calculate set of registries
	 * (this should be all resource types with the @XmlRegistry annotation)
	 */
	protected Set<JavaResourceType> calculateRegistries() {
		return CollectionTools.set(
				new SubIterableWrapper<JavaResourceAbstractType, JavaResourceType>(
					new FilteringIterable<JavaResourceAbstractType>(
							getJaxbProject().getJavaSourceResourceTypes()) {
						@Override
						protected boolean accept(JavaResourceAbstractType o) {
							return o.getKind() == JavaResourceAbstractType.Kind.TYPE 
									&& o.getAnnotation(JAXB.XML_REGISTRY) != null;
						}
					}));
	}
	
	/*
	 * Calculate set of resource types annotated with @XmlType (and not @XmlRegistry)
	 */
	protected Set<JavaResourceAbstractType> calculateInitialPersistentTypes() {
		return CollectionTools.set(
				new FilteringIterable<JavaResourceAbstractType>(getJaxbProject().getJavaSourceResourceTypes()) {
					@Override
					protected boolean accept(JavaResourceAbstractType o) {
						return o.getAnnotation(JAXB.XML_TYPE) != null && o.getAnnotation(JAXB.XML_REGISTRY) == null;
					}
				});
	}
	
	protected void processType(JavaResourceAbstractType resourceType, Set<String> typesToUpdate) {
		JaxbType.Kind jaxbTypeKind = calculateJaxbTypeKind(resourceType);
		String className = resourceType.getQualifiedName();
		
		if (this.types.containsKey(className)) {
			if (this.types.get(className).getKind() == jaxbTypeKind) {
				typesToUpdate.add(className);
				return;
			}
			else {
				this.removeType(className); // this will remove a type of another kind
			}
		}
		
		this.addType(buildType(jaxbTypeKind, resourceType));
	}
	
	protected JaxbType.Kind calculateJaxbTypeKind(JavaResourceAbstractType resourceType) {
		if (resourceType.getKind() == JavaResourceAbstractType.Kind.ENUM) {
			return JaxbType.Kind.PERSISTENT_ENUM;
		}
		// else is of kind TYPE
		else if (resourceType.getAnnotation(JAXB.XML_REGISTRY) != null) {
			return JaxbType.Kind.REGISTRY;
		}
		else if (resourceType.getAnnotation(JAXB.XML_TRANSIENT) != null) {
			return JaxbType.Kind.TRANSIENT;
		}
		else {
			return JaxbType.Kind.PERSISTENT_CLASS;
		}
	}
	
	protected JaxbType buildType(JaxbType.Kind jaxbTypeKind, JavaResourceAbstractType resourceType) {
		if (jaxbTypeKind == JaxbType.Kind.PERSISTENT_ENUM) {
			return buildPersistentEnum((JavaResourceEnum) resourceType);
		}
		else if (jaxbTypeKind == JaxbType.Kind.REGISTRY) {
			return buildRegistry((JavaResourceType) resourceType);
		}
		else if (jaxbTypeKind == JaxbType.Kind.TRANSIENT) {
			return buildTransientClass((JavaResourceType) resourceType);
		}
		else {
			return buildPersistentClass((JavaResourceType) resourceType);
		}
	}
	
	
	// ********** AbstractJaxbNode overrides **********
	
	@Override
	public JaxbProject getJaxbProject() {
		return this.jaxbProject;
	}
	
	@Override
	public IResource getResource() {
		return this.getProject();
	}
	
	protected IProject getProject() {
		return this.jaxbProject.getProject();
	}
	
	
	// ************* packages ***************
	
	public Iterable<JaxbPackage> getPackages() {
		return new LiveCloneIterable<JaxbPackage>(this.packages.values());
	}
	
	public int getPackagesSize() {
		return this.packages.size();
	}

	public JaxbPackage getPackage(String packageName) {
		for (JaxbPackage jaxbPackage : this.getPackages()) {
			if (StringTools.stringsAreEqual(jaxbPackage.getName(), packageName)) {
				return jaxbPackage;
			}
		}
		return null;
	}
	
	protected JaxbPackage addPackage(JaxbPackage contextPackage) {
		if (this.packages.containsKey(contextPackage.getName())) {
			throw new IllegalArgumentException("Package with that name already exists."); //$NON-NLS-1$
		}
		this.packages.put(contextPackage.getName(), contextPackage);
		fireItemAdded(PACKAGES_COLLECTION, contextPackage);
		return contextPackage;
	}
	
	protected void removePackage(JaxbPackage contextPackage) {
		this.removePackage(contextPackage.getName());
	}
	
	protected void removePackage(String packageName) {
		if (! this.packages.containsKey(packageName)) {
			throw new IllegalArgumentException("No package with that name exists."); //$NON-NLS-1$
		}
		JaxbPackage removedPackage = this.packages.remove(packageName);
		fireItemRemoved(PACKAGES_COLLECTION, removedPackage);
	}
	
	protected JaxbPackage buildPackage(String packageName) {
		return this.getFactory().buildPackage(this, packageName);
	}
	
	protected boolean isEmpty(JaxbPackage jaxbPackage) {
		return jaxbPackage.isEmpty();
	}
	
	
	// ********** types ***********
	
	public Iterable<JaxbType> getTypes() {
		return new LiveCloneIterable<JaxbType>(this.types.values());
	}
	
	public int getTypesSize() {
		return this.types.size();
	}
	
	public JaxbType getType(String typeName) {
		return this.types.get(typeName);
	}
	
	protected void addType(JaxbType type) {
		if (this.types.containsKey(type.getFullyQualifiedName())) {
			throw new IllegalArgumentException("Type with that name already exists."); //$NON-NLS-1$
		}
		this.types.put(type.getFullyQualifiedName(), type);
		fireItemAdded(TYPES_COLLECTION, type);
	}
	
	protected void removeType(JaxbType type) {
		removeType(type.getFullyQualifiedName());
	}
	
	protected void removeType(String typeName) {
		if (! this.types.containsKey(typeName)) {
			throw new IllegalArgumentException("No type with that name exists."); //$NON-NLS-1$
		}
		JaxbType removedType = this.types.remove(typeName);
		fireItemRemoved(TYPES_COLLECTION, removedType);
	}
	
	public Iterable<JaxbType> getTypes(final JaxbPackage jaxbPackage) {
		return new FilteringIterable<JaxbType>(getTypes()) {
			@Override
			protected boolean accept(JaxbType o) {
				return o.getPackageName().equals(jaxbPackage.getName());
			}
		};
	}
	
	
	// ********** registries **********
	
	public Iterable<JaxbRegistry> getRegistries() {
		return new SubIterableWrapper<JaxbType, JaxbRegistry>(
				new FilteringIterable<JaxbType>(getTypes()) {
					@Override
					protected boolean accept(JaxbType o) {
						return o.getKind() == JaxbType.Kind.REGISTRY;
					}
				});
	}
	
	protected JaxbRegistry buildRegistry(JavaResourceType resourceType) {
		return this.getFactory().buildRegistry(this, resourceType);
	}
	
	public Iterable<JaxbRegistry> getRegistries(final JaxbPackage jaxbPackage) {
		return new FilteringIterable<JaxbRegistry>(getRegistries()) {
			@Override
			protected boolean accept(JaxbRegistry o) {
				return o.getPackageName().equals(jaxbPackage.getName());
			}
		};
	}


	// ********** transient types **********
	
	public Iterable<JaxbTransientClass> getTransientClasses() {
		return new SubIterableWrapper<JaxbType, JaxbTransientClass>(
				new FilteringIterable<JaxbType>(getTypes()) {
					@Override
					protected boolean accept(JaxbType o) {
						return o.getKind() == JaxbType.Kind.TRANSIENT;
					}
				});
	}
	
	protected JaxbTransientClass buildTransientClass(JavaResourceType resourceType) {
		return this.getFactory().buildJavaTransientClass(this, resourceType);
	}
	
	public Iterable<JaxbTransientClass> getTransientClasses(final JaxbPackage jaxbPackage) {
		return new FilteringIterable<JaxbTransientClass>(getTransientClasses()) {
			@Override
			protected boolean accept(JaxbTransientClass o) {
				return o.getPackageName().equals(jaxbPackage.getName());
			}
		};
	}

	public JaxbTransientClass getTransientClass(String className) {
		for (JaxbTransientClass jaxbClass : this.getTransientClasses()) {
			if (StringTools.stringsAreEqual(jaxbClass.getFullyQualifiedName(), className)) {
				return jaxbClass;
			}
		}
		return null;
	}

	// ********** persistent classes **********
	
	public Iterable<JaxbPersistentClass> getPersistentClasses() {
		return new SubIterableWrapper<JaxbType, JaxbPersistentClass>(
				new FilteringIterable<JaxbType>(getTypes()) {
					@Override
					protected boolean accept(JaxbType o) {
						return o.getKind() == JaxbType.Kind.PERSISTENT_CLASS;
					}
				});
	}
	
	protected JaxbPersistentClass buildPersistentClass(JavaResourceType resourceType) {
		return this.getFactory().buildJavaPersistentClass(this, resourceType);
	}
	
	public Iterable<JaxbPersistentClass> getPersistentClasses(final JaxbPackage jaxbPackage) {
		return new FilteringIterable<JaxbPersistentClass>(getPersistentClasses()) {
			@Override
			protected boolean accept(JaxbPersistentClass o) {
				return o.getPackageName().equals(jaxbPackage.getName());
			}
		};
	}

	public JaxbPersistentClass getPersistentClass(String className) {
		for (JaxbPersistentClass jaxbClass : this.getPersistentClasses()) {
			if (StringTools.stringsAreEqual(jaxbClass.getFullyQualifiedName(), className)) {
				return jaxbClass;
			}
		}
		return null;
	}

	public JaxbClass getClass(String fullyQualifiedTypeName) {
		JaxbPersistentClass jaxbClass= this.getPersistentClass(fullyQualifiedTypeName);
		return jaxbClass != null ? jaxbClass : this.getTransientClass(fullyQualifiedTypeName);
	}

	// ********** persistent enums **********
	
	public Iterable<JaxbPersistentEnum> getPersistentEnums() {
		return new SubIterableWrapper<JaxbType, JaxbPersistentEnum>(
				new FilteringIterable<JaxbType>(getTypes()) {
					@Override
					protected boolean accept(JaxbType o) {
						return o.getKind() == JaxbType.Kind.PERSISTENT_ENUM;
					}
				});
	}
	
	protected JaxbPersistentEnum buildPersistentEnum(JavaResourceEnum resourceEnum) {
		return this.getFactory().buildJavaPersistentEnum(this, resourceEnum);
	}
	
	public Iterable<JaxbPersistentEnum> getPersistentEnums(final JaxbPackage jaxbPackage) {
		return new FilteringIterable<JaxbPersistentEnum>(getPersistentEnums()) {
			@Override
			protected boolean accept(JaxbPersistentEnum o) {
				return o.getPackageName().equals(jaxbPackage.getName());
			}
		};
	}

	public JaxbPersistentEnum getPersistentEnum(String enumName) {
		for (JaxbPersistentEnum jaxbEnum : this.getPersistentEnums()) {
			if (StringTools.stringsAreEqual(jaxbEnum.getFullyQualifiedName(), enumName)) {
				return jaxbEnum;
			}
		}
		return null;
	}

	@Override
    public void stateChanged() {
		super.stateChanged();
		// forward to JAXB project
		this.jaxbProject.stateChanged();
    }
	
	
	// **************** validation ********************************************
	
	public void validate(List<IMessage> messages, IReporter reporter) {
		for (JaxbPackage pkg : this.packages.values()) {
			pkg.validate(messages, reporter);
		}
		for (JaxbType type : this.types.values()) {
			type.validate(messages, reporter);
		}
	}
}
