/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.tools.idea.gradle.project.sync.setup.post;

import static com.android.builder.model.AndroidProject.PROJECT_TYPE_APP;
import static com.android.tools.idea.gradle.project.sync.setup.post.PostSyncProjectSetup.getMaxJavaLanguageLevel;
import static com.android.tools.idea.testing.Facets.createAndAddAndroidFacet;
import static com.google.wireless.android.sdk.stats.GradleSyncStats.Trigger.TRIGGER_PROJECT_CACHED_SETUP_FAILED;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

import com.android.ide.common.gradle.model.IdeAndroidProject;
import com.android.tools.idea.IdeInfo;
import com.android.tools.idea.gradle.project.GradleProjectInfo;
import com.android.tools.idea.gradle.project.ProjectStructure;
import com.android.tools.idea.gradle.project.ProjectStructure.AndroidPluginVersionsInProject;
import com.android.tools.idea.gradle.project.build.GradleProjectBuilder;
import com.android.tools.idea.gradle.project.model.AndroidModelFeatures;
import com.android.tools.idea.gradle.project.model.AndroidModuleModel;
import com.android.tools.idea.gradle.project.sync.GradleSyncInvoker;
import com.android.tools.idea.gradle.project.sync.GradleSyncState;
import com.android.tools.idea.gradle.project.sync.GradleSyncSummary;
import com.android.tools.idea.gradle.project.sync.compatibility.VersionCompatibilityChecker;
import com.android.tools.idea.gradle.project.sync.setup.module.common.DependencySetupIssues;
import com.android.tools.idea.gradle.project.sync.validation.common.CommonModuleValidator;
import com.android.tools.idea.gradle.run.MakeBeforeRunTaskProvider;
import com.android.tools.idea.project.AndroidProjectInfo;
import com.android.tools.idea.testartifacts.junit.AndroidJUnitConfiguration;
import com.android.tools.idea.testartifacts.junit.AndroidJUnitConfigurationType;
import com.intellij.execution.BeforeRunTask;
import com.intellij.execution.RunManagerEx;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.impl.RunManagerImpl;
import com.intellij.mock.MockProgressIndicator;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.testFramework.IdeaTestCase;
import java.util.LinkedList;
import java.util.List;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.annotations.NotNull;
import org.mockito.Mock;

/**
 * Tests for {@link PostSyncProjectSetup}.
 */
public class PostSyncProjectSetupTest extends IdeaTestCase {
  @Mock private IdeInfo myIdeInfo;
  @Mock private GradleProjectInfo myGradleProjectInfo;
  @Mock private GradleSyncInvoker mySyncInvoker;
  @Mock private GradleSyncState mySyncState;
  @Mock private DependencySetupIssues myDependencySetupIssues;
  @Mock private ProjectSetup myProjectSetup;
  @Mock private ModuleSetup myModuleSetup;
  @Mock private GradleSyncSummary mySyncSummary;
  @Mock private PluginVersionUpgrade myVersionUpgrade;
  @Mock private VersionCompatibilityChecker myVersionCompatibilityChecker;
  @Mock private GradleProjectBuilder myProjectBuilder;
  @Mock private CommonModuleValidator.Factory myModuleValidatorFactory;
  @Mock private CommonModuleValidator myModuleValidator;
  @Mock private RunManagerEx myRunManager;
  @Mock private ExternalSystemTaskId myTaskId;

  private ProjectStructureStub myProjectStructure;
  private ProgressIndicator myProgressIndicator;
  private PostSyncProjectSetup mySetup;

  @Override
  protected void setUp() throws Exception {
    super.setUp();
    initMocks(this);

    myProgressIndicator = new MockProgressIndicator();

    Project project = getProject();
    myRunManager = RunManagerImpl.getInstanceImpl(project);
    when(mySyncState.getSummary()).thenReturn(mySyncSummary);
    when(myModuleValidatorFactory.create(project)).thenReturn(myModuleValidator);

    myProjectStructure = new ProjectStructureStub(project);
    mySetup = new PostSyncProjectSetup(project, myIdeInfo, myProjectStructure, myGradleProjectInfo, mySyncInvoker, mySyncState,
                                       myDependencySetupIssues, myProjectSetup, myModuleSetup, myVersionUpgrade,
                                       myVersionCompatibilityChecker, myProjectBuilder, myModuleValidatorFactory, myRunManager);
  }

  @Override
  protected void tearDown() throws Exception {
    myRunManager = null;
    mySetup = null;
    super.tearDown();
  }

  public void testJUnitRunConfigurationSetup() {
    when(myIdeInfo.isAndroidStudio()).thenReturn(true);

    PostSyncProjectSetup.Request request = new PostSyncProjectSetup.Request();
    mySetup.setUpProject(request, myProgressIndicator, myTaskId);
    ConfigurationFactory configurationFactory = AndroidJUnitConfigurationType.getInstance().getConfigurationFactories()[0];
    Project project = getProject();
    AndroidJUnitConfiguration jUnitConfiguration = new AndroidJUnitConfiguration(project, configurationFactory);
    myRunManager.addConfiguration(myRunManager.createConfiguration(jUnitConfiguration, configurationFactory), true);

    List<RunConfiguration> junitRunConfigurations = myRunManager.getConfigurationsList(AndroidJUnitConfigurationType.getInstance());
    for (RunConfiguration runConfiguration : junitRunConfigurations) {
      assertSize(1, myRunManager.getBeforeRunTasks(runConfiguration));
      assertEquals(MakeBeforeRunTaskProvider.ID, myRunManager.getBeforeRunTasks(runConfiguration).get(0).getProviderId());
    }

    RunConfiguration runConfiguration = junitRunConfigurations.get(0);
    List<BeforeRunTask> tasks = new LinkedList<>(myRunManager.getBeforeRunTasks(runConfiguration));

    MakeBeforeRunTaskProvider taskProvider = new MakeBeforeRunTaskProvider(project, AndroidProjectInfo.getInstance(project),
                                                                           GradleProjectInfo.getInstance(project));
    BeforeRunTask newTask = taskProvider.createTask(runConfiguration);
    newTask.setEnabled(true);
    tasks.add(newTask);
    myRunManager.setBeforeRunTasks(runConfiguration, tasks);

    mySetup.setUpProject(request, myProgressIndicator, myTaskId);
    assertSize(2, myRunManager.getBeforeRunTasks(runConfiguration));

    verify(myGradleProjectInfo, times(2)).setNewProject(false);
    verify(myGradleProjectInfo, times(2)).setImportedProject(false);
  }

  // See: https://code.google.com/p/android/issues/detail?id=225938
  public void testSyncWithCachedModelsFinishedWithSyncIssues() {
    when(mySyncState.lastSyncFailedOrHasIssues()).thenReturn(true);

    long lastSyncTimestamp = 2L;
    PostSyncProjectSetup.Request request = new PostSyncProjectSetup.Request();
    request.usingCachedGradleModels = true;
    request.lastSyncTimestamp = lastSyncTimestamp;

    mySetup.setUpProject(request, myProgressIndicator, myTaskId);

    verify(mySyncState, times(1)).syncSkipped(lastSyncTimestamp);
    verify(mySyncInvoker, times(1)).requestProjectSyncAndSourceGeneration(getProject(), TRIGGER_PROJECT_CACHED_SETUP_FAILED);
    verify(myProjectSetup, never()).setUpProject(myProgressIndicator, true);

    verify(myGradleProjectInfo, times(1)).setNewProject(false);
    verify(myGradleProjectInfo, times(1)).setImportedProject(false);
  }

  public void testWithSyncIssueDuringProjectSetup() {
    // Simulate the case when sync issue happens during ProjectSetup.
    when(mySyncState.lastSyncFailedOrHasIssues()).thenReturn(false).thenReturn(true);

    PostSyncProjectSetup.Request request = new PostSyncProjectSetup.Request();
    request.usingCachedGradleModels = false;
    request.lastSyncTimestamp = 1L;

    mySetup.setUpProject(request, myProgressIndicator, myTaskId);

    verify(mySyncState, times(1)).syncFailed(any());
    verify(mySyncState, never()).syncEnded();
  }

  public void testWithExceptionDuringProjectSetup() {
    when(mySyncState.lastSyncFailedOrHasIssues()).thenReturn(false);
    doThrow(new RuntimeException()).when(myProjectSetup).setUpProject(myProgressIndicator, false);

    PostSyncProjectSetup.Request request = new PostSyncProjectSetup.Request();
    request.usingCachedGradleModels = false;
    request.lastSyncTimestamp = 1L;

    try {
      mySetup.setUpProject(request, myProgressIndicator, myTaskId);
      fail();
    }
    catch (Throwable t) {
      // Exception is expected
    }

    verify(mySyncState, times(1)).syncFailed(any());
    verify(mySyncState, never()).syncEnded();
  }

  // See: https://code.google.com/p/android/issues/detail?id=225938
  public void testSyncFinishedWithSyncIssues() {
    when(mySyncState.lastSyncFailedOrHasIssues()).thenReturn(true);

    PostSyncProjectSetup.Request request = new PostSyncProjectSetup.Request();
    request.generateSourcesAfterSync = true;
    request.cleanProjectAfterSync = true;

    mySetup.setUpProject(request, myProgressIndicator, myTaskId);

    Project project = getProject();
    verify(myDependencySetupIssues, times(1)).reportIssues();
    verify(myVersionCompatibilityChecker, times(1)).checkAndReportComponentIncompatibilities(project);

    for (Module module : ModuleManager.getInstance(project).getModules()) {
      verify(myModuleValidator, times(1)).validate(module);
    }

    verify(myModuleValidator, times(1)).fixAndReportFoundIssues();
    verify(myProjectSetup, times(1)).setUpProject(myProgressIndicator, true);
    verify(mySyncState, times(1)).syncFailed(any());
    verify(mySyncState, never()).syncEnded();

    // Source generation should not be invoked if sync failed.
    verify(myProjectBuilder, never()).cleanAndGenerateSources();

    verify(myGradleProjectInfo, times(1)).setNewProject(false);
    verify(myGradleProjectInfo, times(1)).setImportedProject(false);
  }

  public void testCleanIsInvokedWhenGeneratingSourcesAndPluginVersionsChanged() {
    when(mySyncState.lastSyncFailedOrHasIssues()).thenReturn(false);

    PostSyncProjectSetup.Request request = new PostSyncProjectSetup.Request();
    request.generateSourcesAfterSync = true;

    myProjectStructure.currentAgpVersions = new AndroidPluginVersionsInProject() {
      @Override
      public boolean haveVersionsChanged(@NotNull AndroidPluginVersionsInProject other) {
        return true; // Simulate AGP versions have changed between Sync executions.
      }
    };

    mySetup.setUpProject(request, myProgressIndicator, myTaskId);

    // verify "clean" was invoked.
    verify(myProjectBuilder).cleanAndGenerateSources();

    assertTrue(myProjectStructure.analyzed);
  }

  public void testJavaLanguageLevelIsUpdated() {
    // initialize language level to jdk 1.6.
    LanguageLevelProjectExtension ex = LanguageLevelProjectExtension.getInstance(myProject);
    ex.setLanguageLevel(LanguageLevel.JDK_1_6);
    assertEquals(LanguageLevel.JDK_1_6, ex.getLanguageLevel());

    // create two modules with jdk 1.8 and 1.7.
    createAndroidModuleWithLanguageLevel("app", LanguageLevel.JDK_1_8);
    createAndroidModuleWithLanguageLevel("lib", LanguageLevel.JDK_1_7);

    when(mySyncState.lastSyncFailedOrHasIssues()).thenReturn(false);
    PostSyncProjectSetup.Request request = new PostSyncProjectSetup.Request();
    mySetup.setUpProject(request, myProgressIndicator, myTaskId);

    // verify java language level was updated to 1.8.
    assertEquals(LanguageLevel.JDK_1_8, ex.getLanguageLevel());
  }

  public void testGetMaxJavaLangLevelWithDifferentLevels() {
    createAndroidModuleWithLanguageLevel("app", LanguageLevel.JDK_1_7);
    createAndroidModuleWithLanguageLevel("lib", LanguageLevel.JDK_1_8);
    assertEquals(LanguageLevel.JDK_1_8, getMaxJavaLanguageLevel(getProject()));
  }

  public void testGetMaxJavaLangLevelWithSameLevel() {
    createAndroidModuleWithLanguageLevel("app", LanguageLevel.JDK_1_7);
    createAndroidModuleWithLanguageLevel("lib", LanguageLevel.JDK_1_7);
    assertEquals(LanguageLevel.JDK_1_7, getMaxJavaLanguageLevel(getProject()));
  }

  private void createAndroidModuleWithLanguageLevel(@NotNull String moduleName, @NotNull LanguageLevel level) {
    AndroidFacet facet = createAndAddAndroidFacet(createModule(moduleName));
    AndroidModuleModel model = mock(AndroidModuleModel.class);
    facet.getConfiguration().setModel(model);
    when(model.getJavaLanguageLevel()).thenReturn(level);

    // Setup the fields that are necessary to run mySetup.SetUpProject.
    IdeAndroidProject androidProject = mock(IdeAndroidProject.class);
    when(model.getAndroidProject()).thenReturn(androidProject);
    when(androidProject.getProjectType()).thenReturn(PROJECT_TYPE_APP);
    when(model.getFeatures()).thenReturn(mock(AndroidModelFeatures.class));
  }

  private static class ProjectStructureStub extends ProjectStructure {
    AndroidPluginVersionsInProject agpVersionsFromPreviousSync = new AndroidPluginVersionsInProject();
    AndroidPluginVersionsInProject currentAgpVersions = new AndroidPluginVersionsInProject();

    boolean analyzed;

    ProjectStructureStub(@NotNull Project project) {
      super(project);
    }

    @Override
    public void analyzeProjectStructure(@NotNull ProgressIndicator progressIndicator) {
      analyzed = true;
    }

    @Override
    @NotNull
    public AndroidPluginVersionsInProject getAndroidPluginVersions() {
      return analyzed ? currentAgpVersions : agpVersionsFromPreviousSync;
    }
  }
}