/*******************************************************************************
 * Copyright (c) 2012, 2014 Pivotal Software, Inc.
 * 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:
 * Pivotal Software, Inc. - initial API and implementation
 *******************************************************************************/
package org.springsource.ide.eclipse.gradle.core.test;

import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.gradle.tooling.model.eclipse.EclipseProject;
import org.gradle.tooling.model.eclipse.HierarchicalEclipseProject;
import org.springsource.ide.eclipse.gradle.core.GradleCore;
import org.springsource.ide.eclipse.gradle.core.GradleProject;
import org.springsource.ide.eclipse.gradle.core.classpathcontainer.FastOperationFailedException;
import org.springsource.ide.eclipse.gradle.core.modelmanager.IGradleModelListener;


/**
 * Unit tests for GradleProject. 
 * 
 * @author Kris De Volder
 */
public class GradleProjectTest extends GradleTest {
	
	public class TestProjectListener implements IGradleModelListener {
		
		int notifyCount = 0; //Counts number of times the listener is called.
		private GradleProject project;
		private HierarchicalEclipseProject receivedModel;

		/**
		 * @param gradleProject
		 */
		public TestProjectListener(GradleProject gradleProject) {
			this.project = gradleProject;
		}
		
		@Override
		public <T> void modelChanged(GradleProject project, Class<T> type,
				T model) {
			assertEquals(this.project, project);
			try {
				receivedModel = project.getSkeletalGradleModel();
			} catch (Exception e) {
				throw new Error(e);
			}
			notifyCount++;
		}

		public void checkExpected(Class<? extends HierarchicalEclipseProject> expectModelType, int expectCount) {
			assertEquals(expectCount, notifyCount);
			assertTrue(expectModelType.isAssignableFrom(receivedModel.getClass()));
		}
	}

	public void testProjectModelListener() throws Exception {
		//TODO: model manager, this tests behavior is not compaptible with new model listeners.
		String[] projectNames = {
				"multiproject",
				"api",
				"services",
				"services-shared",
				"webservice",
				"shared"
		};
		
		importSampleProject(projectNames[0]);
		
		assertProjects(
				projectNames
		);
		
		IJavaProject shared = getJavaProject("shared");
		assertSourceFolder(shared, "src/main/java");
		assertSourceFolder(shared, "src/main/resources");
		assertSourceFolder(shared, "src/test/java");
		assertSourceFolder(shared, "src/test/resources");
		
		GradleProject[] projects = new GradleProject[projectNames.length];
		TestProjectListener[] listeners = new TestProjectListener[projectNames.length];
		for (int i = 0; i < projects.length; i++) {
			projects[i] = GradleCore.create(getProject(projectNames[i]));
			listeners[i] = new TestProjectListener(projects[i]);
			projects[i].addModelListener(listeners[i]);
		}
		
		//After projects where build by Eclipse, we expect all projects to have full models
		for (GradleProject project : projects) {
			try {
				project.getGradleModel(); //no Fast
			} catch (FastOperationFailedException e) {
				fail("Project "+project+" doesn't have a model");
			}
		}
		
		//Invalidate the models
		projects[0].invalidateGradleModel();
		
		//With Group model provider, invalidating one project should invalidate all
		for (GradleProject project : projects) {
			try {
				project.getSkeletalGradleModel();
				fail("Project "+project+" still has a model");
			} catch (FastOperationFailedException e) {
				//expected!
			}
		}
		
		//With Group model provider, forcing one model build should force all related models
		//to become available.
		projects[3].getSkeletalGradleModel(new NullProgressMonitor()); 
		for (TestProjectListener listener : listeners) {
			listener.checkExpected(HierarchicalEclipseProject.class, 1);
		}

		//Forcing more detailed model should cause another round of update events.
		projects[2].getGradleModel(new NullProgressMonitor()); 
		for (TestProjectListener listener : listeners) {
			listener.checkExpected(EclipseProject.class, 2);
		}
		
	}

}

@@ -1774,40 +1774,42 @@
 l = 
-project.getSkeletalGradleM
+(HierarchicalEclipseProject) m
 odel
-()
 ;%0A%09%09
@@ -2050,16 +2050,124 @@
 ertTrue(
+expectModelType.getSimpleName()+%22 is not assignable from %22+ receivedModel.getClass().getSimpleName() ,%0A%09%09%09%09%09
 expectMo
@@ -2290,98 +2290,8 @@
 n %7B%0A
-%09%09//TODO: model manager, this tests behavior is not compaptible with new model listeners.%0A
 %09%09St
@@ -3309,16 +3309,40 @@
 /no Fast
+OperationFailedException
 %0A%09%09%09%7D ca
@@ -3478,125 +3478,91 @@
 s%0A%09%09
-projects%5B0%5D.invalidateGradleModel();%0A%09%09%0A%09%09//With Group model provider, invalidating one project should invalidate all
+for (GradleProject project : projects) %7B%0A%09%09%09project.invalidateGradleModel();%0A%09%09%7D%0A%09%09
 %0A%09%09f

Fix failing test case