/*******************************************************************************
 * Copyright (c) 2009 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.core.internal.jpa2;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
import java.util.Map.Entry;

import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jpt.core.context.AttributeMapping;
import org.eclipse.jpt.core.context.PersistentAttribute;
import org.eclipse.jpt.core.context.PersistentType;
import org.eclipse.jpt.core.jpa2.PersistentTypeMetamodelSynchronizer;
import org.eclipse.jpt.core.jpa2.context.AttributeMapping2_0;
import org.eclipse.jpt.core.jpa2.context.MetamodelField;
import org.eclipse.jpt.core.jpa2.resource.java.JPA2_0;
import org.eclipse.jpt.utility.Filter;
import org.eclipse.jpt.utility.internal.ClassTools;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.IndentingPrintWriter;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.Transformer;
import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
import org.eclipse.jpt.utility.internal.iterables.TransformationIterable;

import com.ibm.icu.text.Collator;
import com.ibm.icu.text.DateFormat;

/**
 * 
 */
@SuppressWarnings("nls")
public class GenericPersistentTypeMetamodelSynchronizer
	implements PersistentTypeMetamodelSynchronizer
{
	protected final Owner owner;
	protected final PersistentType persistentType;
	protected final String metamodelClassName;


	public GenericPersistentTypeMetamodelSynchronizer(Owner owner, PersistentType persistentType) {
		super();
		this.owner = owner;
		this.persistentType = persistentType;
		this.metamodelClassName = this.buildMetamodelClassName();
	}

	// TODO
	protected String buildMetamodelClassName() {
		return this.buildMetamodelClassName(this.persistentType.getName());
	}

	protected String buildMetamodelClassName(String className) {
		return className + '_';
	}

	// TODO
	protected String getPackageName() {
		return ClassTools.packageNameForClassNamed(this.metamodelClassName);
	}

	protected IPackageFragment buildPackageFragment() {
		IPackageFragmentRoot sourceFolder = this.owner.getSourceFolder();
		String pkgName = this.getPackageName();
		IPackageFragment packageFragment = sourceFolder.getPackageFragment(pkgName);
		if (packageFragment.exists()) {
			return packageFragment;
		}
		try {
			return sourceFolder.createPackageFragment(pkgName, true, null);
		} catch (JavaModelException ex) {
			throw new RuntimeException(ex);
		}
	}

	public void synchronize() {
		try {
			this.synchronize_();
		} catch (JavaModelException ex) {
			throw new RuntimeException(ex);
		}
	}

	protected void synchronize_() throws JavaModelException {
		IPackageFragment pkg = this.buildPackageFragment();
		String fileName = ClassTools.shortNameForClassNamed(this.metamodelClassName) + ".java";

		ISourceReference oldSourceRef = pkg.getCompilationUnit(fileName);
		String oldSource = oldSourceRef.exists() ? oldSourceRef.getSource() : null;

		if (oldSource == null) {  // write a new file
			pkg.createCompilationUnit(fileName, this.buildSource(), false, null);  // false=no force
			return;
		}

		int oldBegin = oldSource.indexOf(DALI_TAG);
		if (oldBegin == -1) {
			return;
		}
		oldBegin += DALI_TAG_LENGTH;

		int oldEnd = oldSource.indexOf('"', oldBegin);
		if (oldEnd == -1) {
			return;
		}
		String oldSource2 = oldSource.replace(oldSource.substring(oldBegin, oldEnd), "");

		String newSource = this.buildSource();
		int newBegin = newSource.indexOf(DALI_TAG) + DALI_TAG_LENGTH;
		int newEnd = newSource.indexOf('"', newBegin);
		String newSource2 = newSource.replace(newSource.substring(newBegin, newEnd), "");

		if ( ! newSource2.equals(oldSource2)) {  // replace the old file
			pkg.createCompilationUnit(fileName, newSource, true, null);
		}
	}

	protected static final String DALI_TAG = "@Generated(\"Dali";
	protected static final int DALI_TAG_LENGTH = DALI_TAG.length();

	/**
	 * build the "body" source first; then build the "package" and "imports" source
	 * and concatenate the "body" source to it
	 */
	protected String buildSource() {
		// build the body source first so we can gather up the import statements
		BodySourceWriter bodySourceWriter = this.buildBodySourceWriter();

		StringWriter sw = new StringWriter(bodySourceWriter.getLength() + 2000);
		PrintWriter pw = new PrintWriter(sw);
		this.printPackageAndImportsOn(pw, bodySourceWriter);
		pw.print(bodySourceWriter.getSource());
		return sw.toString();
	}

	protected BodySourceWriter buildBodySourceWriter() {
		BodySourceWriter pw = new BodySourceWriter(this.getPackageName(), this.metamodelClassName);
		this.printBodySourceOn(pw);
		return pw;
	}

	protected void printBodySourceOn(BodySourceWriter pw) {
		this.printClassDeclarationOn(pw);
		pw.print(" {");
		pw.println();

		pw.indent();
			this.printAttributesOn(pw);
		pw.undent();

		pw.print('}');
		pw.println();  // EOF
	}


	// ********** class declaration **********

	protected void printClassDeclarationOn(BodySourceWriter pw) {
		this.printGeneratedAnnotationOn(pw);
		this.printStaticMetamodelAnnotationOn(pw);

		pw.print("public class ");
		pw.printTypeDeclaration(this.metamodelClassName);
		PersistentType superPersistentType = this.persistentType.getSuperPersistentType();
		if (superPersistentType != null) {
			pw.print(" extends ");
			pw.printTypeDeclaration(this.buildMetamodelClassName(superPersistentType.getName()));
		}
	}

	protected void printStaticMetamodelAnnotationOn(BodySourceWriter pw) {
		pw.printAnnotation(JPA2_0.STATIC_METAMODEL);
		pw.print('(');
		pw.printTypeDeclaration(this.persistentType.getName());
		pw.print(".class");
		pw.print(')');
		pw.println();
	}

	// TODO - comment?
	protected void printGeneratedAnnotationOn(BodySourceWriter pw) {
		pw.printAnnotation("javax.annotation.Generated");
		pw.print('(');
		pw.printStringLiteral("Dali" + ' ' + DateFormat.getDateTimeInstance().format(new Date()));
		pw.print(')');
		pw.println();
	}


	// ********** attributes **********

	protected void printAttributesOn(BodySourceWriter pw) {
		for (Iterator<PersistentAttribute> stream = this.persistentType.attributes(); stream.hasNext(); ) {
			this.printAttributeOn(stream.next(), pw);
		}
	}

	protected void printAttributeOn(PersistentAttribute persistentAttribute, BodySourceWriter pw) {
		AttributeMapping attributeMapping = persistentAttribute.getMapping();
		if (attributeMapping != null) {  // probably shouldn't be null?
			this.printAttributeMappingOn(attributeMapping, pw);
		}
	}

	protected void printAttributeMappingOn(AttributeMapping attributeMapping, BodySourceWriter pw) {
		MetamodelField field = ((AttributeMapping2_0) attributeMapping).getMetamodelField();
		if (field != null) {
			this.printFieldOn(field, pw);
		}
	}

	protected void printFieldOn(MetamodelField field, BodySourceWriter pw) {
		for (String modifier : field.getModifiers()) {
			pw.print(modifier);
			pw.print(' ');
		}
		pw.printTypeDeclaration(field.getTypeName());
		pw.print('<');
		for (Iterator<String> stream = field.getTypeArgumentNames().iterator(); stream.hasNext(); ) {
			pw.printTypeDeclaration(stream.next());
			if (stream.hasNext()) {
				pw.print(", ");
			}
		}
		pw.print('>');
		pw.print(' ');
		pw.print(field.getName());
		pw.print(';');
		pw.println();
	}


	// ********** package and imports **********

	protected void printPackageAndImportsOn(PrintWriter pw, BodySourceWriter bodySourceWriter) {
		if (this.getPackageName().length() != 0) {
			pw.print("package ");
			pw.print(this.getPackageName());
			pw.print(';');
			pw.println();
			pw.println();
		}

		for (String import_ : bodySourceWriter.getImports()) {
			pw.print("import ");
			pw.print(import_);
			pw.print(';');
			pw.println();
		}
		pw.println();
	}


	// ********** source writer **********

	/**
	 * Extend IndentingPrintWriter with some methods that facilitate building
	 * class source code.
	 */
	protected static class BodySourceWriter
		extends IndentingPrintWriter
	{
		protected final String packageName;
		protected final String className;
		// key = short class name; value = import package
		protected final HashMap<String, ImportPackage> imports = new HashMap<String, ImportPackage>();

		protected BodySourceWriter(String packageName, String className) {
			super(new StringWriter(2000));
			this.packageName = packageName;
			this.className = className;
		}

		protected String getSource() {
			return this.out.toString();
		}

		protected int getLength() {
			return ((StringWriter) this.out).getBuffer().length();
		}

		protected void printVisibility(String visibilityModifier) {
			if (visibilityModifier.length() != 0) {
				this.print(visibilityModifier);
				this.print(' ');
			}
		}

		protected void printAnnotation(String annotationName) {
			this.print('@');
			this.printTypeDeclaration(annotationName);
		}

		protected void printTypeDeclaration(String typeDeclaration) {
			this.print(this.buildImportedTypeDeclaration(typeDeclaration));
		}

		protected void printField(String fieldName, String typeDeclaration, String visibility) {
			this.printVisibility(visibility);
			this.printTypeDeclaration(typeDeclaration);
			this.print(' ');
			this.print(fieldName);
			this.print(';');
			this.println();
			this.println();
		}

		protected void printParameterizedField(String fieldName, String typeDeclaration, String parameterTypeDeclaration, String visibility) {
			this.printVisibility(visibility);
			this.printTypeDeclaration(typeDeclaration);
			this.print('<');
			this.printTypeDeclaration(parameterTypeDeclaration);
			this.print('>');
			this.print(' ');
			this.print(fieldName);
			this.print(';');
			this.println();
			this.println();
		}

		/**
		 * Convert the specified string to a String Literal and print it,
		 * adding the surrounding double-quotes and escaping characters
		 * as necessary.
		 */
		void printStringLiteral(String string) {
			StringTools.convertToJavaStringLiteralOn(string, this);
		}


		// ********** imports **********

		// ***** writing
		/**
		 * Return the specified class's "imported" name.
		 * The class declaration must be of the form:
		 *     "int"
		 *     "int[]" (not "[I")
		 *     "java.lang.Object"
		 *     "java.lang.Object[]" (not "[Ljava.lang.Object;")
		 *     "java.util.Map.Entry" (not "java.util.Map$Entry")
		 *     "java.util.Map.Entry[][]" (not "[[Ljava.util.Map$Entry;")
		 *     
		 * To really do this right, we would need to gather all the types from
		 * the "unamed" (default) package that were referenced in the
		 * compilation unit beforehand. *Any* collisions with one of these
		 * types would have to be fully qualified (whether it was from
		 * 'java.lang' or the same package as the current compilation unit).
		 * In other words, if we have any types from the "unnamed" package,
		 * results are unpredictable....
		 */
		protected String buildImportedTypeDeclaration(String typeDeclaration) {
			if (this.typeDeclarationIsMemberClass(typeDeclaration)) {
				// no need for an import, just return the partially-qualified name
				return this.buildMemberClassTypeDeclaration(typeDeclaration);
			}
			int last = typeDeclaration.lastIndexOf('.');
			String currentPackageName = (last == -1) ? "" : typeDeclaration.substring(0, last);
			String shortTypeDeclaration = typeDeclaration.substring(last + 1);
			String shortElementTypeName = shortTypeDeclaration;
			while (shortElementTypeName.endsWith("[]")) {
				shortElementTypeName = shortElementTypeName.substring(0, shortElementTypeName.length() - 2);
			}
			ImportPackage prev = this.imports.get(shortElementTypeName);
			if (prev == null) {
				// this is the first class with this short element type name
				this.imports.put(shortElementTypeName, new ImportPackage(currentPackageName));
				return shortTypeDeclaration;
			}
			if (prev.packageName.equals(currentPackageName)) {
				// this element type has already been imported
				return shortTypeDeclaration;
			}
			if (currentPackageName.equals(this.packageName) &&
					prev.packageName.equals("java.lang")) {
				// we force the 'java.lang' class to be explicitly imported
				prev.collision = true;
			}
			// another class with the same short element type name has been
			// previously imported, so this one must be used fully-qualified
			return typeDeclaration;
		}

		/**
		 * e.g. "foo.bar.Employee.PK" will return true
		 */
		protected boolean typeDeclarationIsMemberClass(String typeDeclaration) {
			return (typeDeclaration.length() > this.className.length())
					&& typeDeclaration.startsWith(this.className)
					&& (typeDeclaration.charAt(this.className.length()) == '.');
		}

		/**
		 * e.g. "foo.bar.Employee.PK" will return "Employee.PK"
		 * this prevents collisions with other imported classes (e.g. "joo.jar.PK")
		 */
		protected String buildMemberClassTypeDeclaration(String typeDeclaration) {
			int index = this.packageName.length();
			if (index != 0) {
				index++;  // bump past the '.'
			}
			return typeDeclaration.substring(index);
		}

		// ***** reading
		protected Iterable<String> getImports() {
			return this.getSortedRequiredImports();
		}

		/**
		 * transform our map entries to class names
		 */
		protected Iterable<String> getSortedRequiredImports() {
			return new TransformationIterable<Map.Entry<String, ImportPackage>, String>(this.getSortedRequiredImportEntries(), this.buildImportEntriesTransformer());
		}

		protected Transformer<Map.Entry<String, ImportPackage>, String> buildImportEntriesTransformer() {
			return IMPORT_ENTRIES_TRANSFORMER;
		}

		protected static final Transformer<Map.Entry<String, ImportPackage>, String> IMPORT_ENTRIES_TRANSFORMER = new ImportEntriesTransformer();

		protected static class ImportEntriesTransformer
			implements Transformer<Map.Entry<String, ImportPackage>, String>
		{
			public String transform(Entry<String, ImportPackage> importEntry) {
				String pkg = importEntry.getValue().packageName;
				String type = importEntry.getKey();
				StringBuilder sb = new StringBuilder(pkg.length() + 1 + type.length());
				sb.append(pkg);
				sb.append('.');
				sb.append(type);
				return sb.toString();
			}
		}

		/**
		 * sort by package first, then class (*not* by fully-qualified class name)
		 */
		protected Iterable<Map.Entry<String, ImportPackage>> getSortedRequiredImportEntries() {
			TreeSet<Map.Entry<String, ImportPackage>> sortedEntries = new TreeSet<Map.Entry<String, ImportPackage>>(this.buildImportEntriesComparator());
			CollectionTools.addAll(sortedEntries, this.getRequiredImportEntries());
			return sortedEntries;
		}

		protected Comparator<Map.Entry<String, ImportPackage>> buildImportEntriesComparator() {
			return IMPORT_ENTRIES_COMPARATOR;
		}

		protected static final Comparator<Map.Entry<String, ImportPackage>> IMPORT_ENTRIES_COMPARATOR = new ImportEntriesComparator();

		protected static class ImportEntriesComparator
			implements Comparator<Map.Entry<String, ImportPackage>>
		{
			public int compare(Map.Entry<String, ImportPackage> e1, Map.Entry<String, ImportPackage> e2) {
				Collator collator = Collator.getInstance();
				int pkg = collator.compare(e1.getValue().packageName, e2.getValue().packageName);
				return (pkg == 0) ? collator.compare(e1.getKey(), e2.getKey()) : pkg;
			}
		}

		/**
		 * strip off any non-required imports (e.g. "java.lang.Object')
		 */
		protected Iterable<Map.Entry<String, ImportPackage>> getRequiredImportEntries() {
			return new FilteringIterable<Map.Entry<String, ImportPackage>, Map.Entry<String, ImportPackage>>(this.imports.entrySet(), this.buildRequiredImportEntriesFilter());
		}

		protected Filter<Map.Entry<String, ImportPackage>> buildRequiredImportEntriesFilter() {
			return new RequiredImportEntriesFilter();
		}

		protected class RequiredImportEntriesFilter
			implements Filter<Map.Entry<String, ImportPackage>>
		{
			public boolean accept(Map.Entry<String, ImportPackage> importEntry) {
				return this.packageMustBeImported(importEntry.getValue());
			}

			protected boolean packageMustBeImported(ImportPackage importPackage) {
				String pkg = importPackage.packageName;
				if (pkg.equals("")) {
					// cannot import a type from the "unnamed" package
					return false;
				}
				if (pkg.equals("java.lang")) {
					// we must import from 'java.lang' if we also have a class in the same package
					return importPackage.collision;
				}
				if (pkg.equals(BodySourceWriter.this.packageName)) {
					// we never need to import a class from the same package
					return false;
				}
				return true;
			}
		}

		/**
		 * We need a 'collision' flag for when we encounter a class from
		 * 'java.lang' followed by a class from the current compilation unit's
		 * package. We will need to include the explicit import of the
		 * 'java.lang' class and all the references to the other class will
		 * have to be fully-qualified.
		 * 
		 * If the classes are encountered in the opposite order (i.e. the class
		 * from the current compilation unit's package followed by the class
		 * from 'java.lang'), we do *not* need to import the first class while
		 * all the references to the 'java.lang' class will be fully-qualified.
		 * 
		 * Unfortunately, we still have a problem: if we reference a class from
		 * 'java.lang' and there is a conflicting class from the current
		 * compilation unit's package (but that class is *not* revealed to us
		 * here), the simple name will be resolved to the non-'java.lang' class.
		 * Unless we simply force an import of *all* 'java.lang' classes.... :-(
		 * 
		 * This shouldn't happen very often. :-)
		 */
		protected static class ImportPackage {
			protected final String packageName;
			protected boolean collision = false;

			protected ImportPackage(String packageName) {
				super();
				this.packageName = packageName;
			}
		}

	}

}
