/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.ui.tests.typeconstraints;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;

import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor;
import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TypeEnvironment;

import org.eclipse.jdt.ui.tests.refactoring.RefactoringTestSetup;
import org.eclipse.jdt.ui.tests.refactoring.infra.AbstractCUTestCase;
import org.eclipse.jdt.ui.tests.refactoring.infra.RefactoringTestPlugin;

public class TypeEnvironmentTests extends AbstractCUTestCase {

	private static final boolean BUG_83616_core_wildcard_assignments= true;

	private static class MyTestSetup extends RefactoringTestSetup {
		private static IPackageFragment fSignaturePackage;
		private static IPackageFragment fGenericPackage;
		public MyTestSetup(Test test) {
			super(test);
		}
		protected void setUp() throws Exception {
			super.setUp();
			fSignaturePackage= getDefaultSourceFolder().createPackageFragment("signature", true, null);
			fGenericPackage= getDefaultSourceFolder().createPackageFragment("generic", true, null);
		}
		public static IPackageFragment getSignaturePackage() {
			return fSignaturePackage;
		}
		public static IPackageFragment getGenericPackage() {
			return fGenericPackage;
		}
	}
	
	private static class CreationChecker extends HierarchicalASTVisitor {
		private TypeEnvironment fTypeEnvironment;
		public CreationChecker() {
			fTypeEnvironment= new TypeEnvironment();
		}
		public boolean visit(SimpleName node) {
			IBinding binding= node.resolveBinding();
			if (!(binding instanceof ITypeBinding)) 
				return true;
			checkTypeBinding(binding);
			return true;
		}
		private void checkTypeBinding(IBinding binding) {
			ITypeBinding type= (ITypeBinding)binding;
			if (!(type.isPrimitive() && type.getName().equals("void"))) {
				TType refType= fTypeEnvironment.create(type);
				assertNotNull("Refactoring type is null", refType);
				assertEquals("Not same name", type.getName(), refType.getName());
				assertEquals("Not same signature", PrettySignatures.get(type), refType.getPrettySignature());
				assertTrue("Not same type", refType == fTypeEnvironment.create(type));
			}
		}
		public boolean visit(org.eclipse.jdt.core.dom.Type node) {
			checkTypeBinding(node.resolveBinding());
			return true;
		}
	}
	
	private static class TypeBindingCollector extends ASTVisitor {
		private List fResult= new ArrayList();
		private List fWildcards= new ArrayList();
		public boolean visit(FieldDeclaration node) {
			VariableDeclarationFragment fragment= (VariableDeclarationFragment)node.fragments().get(0);
			if (fragment.getName().getIdentifier().equals("NullType")) {
				fResult.add(fragment.getInitializer().resolveTypeBinding());
			} else {
				fResult.add(fragment.resolveBinding().getType());
			}
			return false;
		}
		public void endVisit(CompilationUnit node) {
			for (Iterator iter= fResult.iterator(); iter.hasNext();) {
				ITypeBinding binding= (ITypeBinding)iter.next();
				if (binding.isParameterizedType()) {
					ITypeBinding[] args= binding.getTypeArguments();
					for (int i= 0; i < args.length; i++) {
						if (args[i].isWildcardType()) {
							fWildcards.add(args[i]);
						}
					}
				}
			}
		}
		public ITypeBinding[] getResult() {
			return (ITypeBinding[])fResult.toArray(new ITypeBinding[fResult.size()]);
		}
		public ITypeBinding[] getWildcards() {
			return (ITypeBinding[])fWildcards.toArray(new ITypeBinding[fWildcards.size()]);
		}
	}
	
	private static class CaptureTypeBindingCollector extends ASTVisitor {
		private List fResult= new ArrayList();
		public boolean visit(Assignment node) {
			Expression expression= node.getRightHandSide();
			ITypeBinding typeBinding= expression.resolveTypeBinding();
			fResult.add(typeBinding);
			collectTypeArgumentBindings(typeBinding, fResult);
			return false;
		}
		private void collectTypeArgumentBindings(ITypeBinding typeBinding, List result) {
			if (! typeBinding.isParameterizedType())
				return;
			ITypeBinding[] typeArguments= typeBinding.getTypeArguments();
			for (int i= 0; i < typeArguments.length; i++) {
				ITypeBinding typeArgument= typeArguments[i];
				if (BUG_83616_core_wildcard_assignments && typeArgument.isParameterizedType() && typeArgument.getTypeArguments()[0].isWildcardType())
					continue;
				result.add(typeArgument);
				collectTypeArgumentBindings(typeArgument, result);
			}
		}
		public ITypeBinding[] getResult() {
			return (ITypeBinding[])fResult.toArray(new ITypeBinding[fResult.size()]);
		}
	}
	
	
	public TypeEnvironmentTests(String name) {
		super(name);
	}

	public static Test suite() {
		return new MyTestSetup(new TestSuite(TypeEnvironmentTests.class));
	}
	
	public static Test setUpTest(Test someTest) {
		return new MyTestSetup(someTest);
	}
	
	protected InputStream getFileInputStream(String fileName) throws IOException {
		return RefactoringTestPlugin.getDefault().getTestResourceStream(fileName);
	}
	
	protected String getResourceLocation() {
		return "TypeEnvironment/TestProject/";
	}
	
	protected String adaptName(String name) {
		return Character.toUpperCase(name.charAt(0)) + name.substring(1) + ".java";
	}
	
	private ASTNode createAST(IPackageFragment pack) throws Exception {
		IJavaProject project= pack.getJavaProject();
		ASTParser parser= ASTParser.newParser(AST.JLS3);
		parser.setProject(project);
		parser.setResolveBindings(true);
		ICompilationUnit unit= createCU(pack, getName());
		parser.setSource(unit);
		return parser.createAST(null);
	}
	
	//---- creation ----------------------------------------------------------
	
	private void performCreationTest() throws Exception {
		createAST(MyTestSetup.getSignaturePackage()).accept(new CreationChecker());
	}
	
	public void testArrays() throws Exception {
		performCreationTest();
	}
	
	public void testStandardTypes() throws Exception {
		performCreationTest();
	}

	public void testRawTypes() throws Exception {
		performCreationTest();
	}
	
	public void testGenericTypes() throws Exception {
		performCreationTest();
	}
	
	public void testWildcardTypes() throws Exception {
		performCreationTest();
	}
	
	public void testPrimitiveTypes() throws Exception {
		performCreationTest();
	}
	
	public void testTypeVariables() throws Exception {
		performCreationTest();
	}
	
	//---- generic assigment test ----------------------------------------------
	
	private void performGenericAssignmentTest() throws Exception {
		ASTNode node= createAST(MyTestSetup.getGenericPackage());
		TypeBindingCollector collector= new TypeBindingCollector();
		node.accept(collector);
		testBindings(collector.getResult());
		testAssignment(collector.getWildcards());
	}

	private void testBindings(ITypeBinding[] bindings) throws Exception {
		TType[] types= new TType[bindings.length];
		TypeEnvironment environment= new TypeEnvironment();
		for (int i= 0; i < bindings.length; i++) {
			types[i]= environment.create(bindings[i]);
			assertEquals("Not same name", bindings[i].getName(), types[i].getName());
			assertEquals("Not same signature", PrettySignatures.get(bindings[i]), types[i].getPrettySignature());
			assertEquals("Not same modifiers", bindings[i].getModifiers(), types[i].getModifiers());
			testFlags(bindings[i], types[i]);
			assertTrue("Not same erasure", types[i].getErasure().isEqualTo(bindings[i].getErasure()));
			assertTrue("Not same type declaration", types[i].getTypeDeclaration().isEqualTo(bindings[i].getTypeDeclaration()));
			assertTrue("Not same type", types[i] == environment.create(bindings[i]));
			
		}
		for (int o= 0; o < bindings.length; o++) {
			for (int i= 0; i < bindings.length; i++) {
				checkCanAssignTo(bindings[o], bindings[i], types[o], types[i]);
			}
		}
		TypeEnvironment secondEnvironment= new TypeEnvironment();
		for (int i= 0; i < bindings.length; i++) {
			assertTrue("Equal to second environment", types[i].equals(secondEnvironment.create(bindings[i])));
		}
		ITypeBinding[] restoredBindings= TypeEnvironment.createTypeBindings(types, RefactoringTestSetup.getProject());
		assertEquals("Not same length", restoredBindings.length, bindings.length);
		for (int i= 0; i < restoredBindings.length; i++) {
			assertTrue("Not same binding", bindings[i].isEqualTo(restoredBindings[i]));
		}
	}

	private void checkCanAssignTo(ITypeBinding rhsBinding, ITypeBinding lhsBinding, TType rhs, TType lhs) {
		boolean coreResult= rhsBinding.isAssignmentCompatible(lhsBinding);
		boolean uiResult= rhs.canAssignTo(lhs);
		if (coreResult != uiResult) {
			if (lhs.isCaptureType() || rhs.isCaptureType()) { // see bug 93082
				System.out.println("Different assignment rule(" +
					PrettySignatures.get(lhsBinding) + "= " + PrettySignatures.get(rhsBinding) + 
					"): Bindings<" + coreResult +
					"> TType<" + uiResult + ">");
				return;
			}
		}
		
		assertEquals("Different assignment rule(" + 
			PrettySignatures.get(lhsBinding) + "= " + PrettySignatures.get(rhsBinding) + 
			"): ", coreResult, uiResult);
	}
	
	private void testAssignment(ITypeBinding[] bindings) {
		TType[] types= new TType[bindings.length];
		TypeEnvironment environment= new TypeEnvironment();
		for (int i= 0; i < bindings.length; i++) {
			types[i]= environment.create(bindings[i]);
		}
		for (int o= 0; o < bindings.length; o++) {
			for (int i= 0; i < bindings.length; i++) {
				ITypeBinding oBinding= bindings[o];
				ITypeBinding iBinding= bindings[i];
				boolean coreResult= oBinding.isAssignmentCompatible(iBinding);
				TType oType= types[o];
				TType iType= types[i];
				boolean uiResult= oType.canAssignTo(iType);
				if (coreResult != uiResult && !oType.isWildcardType() && ! BUG_83616_core_wildcard_assignments) { // see bug 83616
					System.out.println("Different assignment rule(" +
						PrettySignatures.get(iBinding) + "= " + PrettySignatures.get(oBinding) + 
						"): Bindings<" + coreResult +
						"> TType<" + uiResult + ">");
				}
			}
		}
	}
	
	private void testFlags(ITypeBinding binding, TType type) {
		assertEquals("Different class flag", binding.isClass(), type.isClass());
		assertEquals("Different enum flag", binding.isEnum(), type.isEnum());
		assertEquals("Different interface  flag", binding.isInterface(), type.isInterface());
		assertEquals("Different annotation flag", binding.isAnnotation(), type.isAnnotation());
		
		assertEquals("Different top level flag", binding.isTopLevel(), type.isTopLevel());
		assertEquals("Different nested flag", binding.isNested(), type.isNested());
		assertEquals("Different local flag", binding.isLocal(), type.isLocal());
		assertEquals("Different member flag", binding.isMember(), type.isMember());
		assertEquals("Different anonymous flag", binding.isAnonymous(), type.isAnonymous());
	}
	
	public void testStandardAssignments() throws Exception {
		performGenericAssignmentTest();
	}	
	
	public void testWildcardAssignments() throws Exception {
		performGenericAssignmentTest();
	}

	public void testTypeVariableAssignments() throws Exception {
		performGenericAssignmentTest();
	}
	
	public void testCaptureAssignments() throws Exception {
		ASTNode node= createAST(MyTestSetup.getGenericPackage());
		CaptureTypeBindingCollector collector= new CaptureTypeBindingCollector();
		node.accept(collector);
		testBindings(collector.getResult());
	}

	public void _testAssignment() throws Exception {
		ASTNode node= createAST(MyTestSetup.getGenericPackage());
		TypeBindingCollector collector= new TypeBindingCollector();
		node.accept(collector);
		ITypeBinding[] bindings= collector.getResult();
		TType[] types= new TType[bindings.length];
		TypeEnvironment environment= new TypeEnvironment();
		for (int i= 0; i < bindings.length; i++) {
			types[i]= environment.create(bindings[i]);
		}
		System.out.println(PrettySignatures.get(bindings[0]) + "= " + PrettySignatures.get(bindings[1]) +
			": " + bindings[1].isAssignmentCompatible(bindings[0]));
		// types[1].canAssignTo(types[0]);
	}
	
	public void _testParameterizedToGeneric() throws Exception {
		ASTNode node= createAST(MyTestSetup.getGenericPackage());
		TypeBindingCollector collector= new TypeBindingCollector();
		node.accept(collector);
		ITypeBinding[] bindings= collector.getResult();
		bindings[0]= bindings[0].getTypeDeclaration();
		System.out.println(PrettySignatures.get(bindings[0]) + "= " + PrettySignatures.get(bindings[1]) +
			": " + bindings[1].isAssignmentCompatible(bindings[0]));
		System.out.println(PrettySignatures.get(bindings[0]) + "= " + PrettySignatures.get(bindings[0]) +
			": " + bindings[0].isAssignmentCompatible(bindings[0]));
		bindings[1]= bindings[1].getTypeDeclaration();
		System.out.println(PrettySignatures.get(bindings[0]) + "= " + PrettySignatures.get(bindings[1]) +
			": " + bindings[1].isAssignmentCompatible(bindings[0]));
	}
}
