/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * 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.google.idea.blaze.android.project;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

import com.android.tools.idea.project.BuildSystemService;
import com.google.common.collect.Maps;
import com.google.idea.blaze.android.sync.model.AndroidResourceModule;
import com.google.idea.blaze.android.sync.model.AndroidResourceModuleRegistry;
import com.google.idea.blaze.base.BlazeTestCase;
import com.google.idea.blaze.base.actions.BlazeBuildService;
import com.google.idea.blaze.base.ideinfo.ArtifactLocation;
import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
import com.google.idea.blaze.base.ideinfo.TargetKey;
import com.google.idea.blaze.base.ideinfo.TargetMap;
import com.google.idea.blaze.base.ideinfo.TargetMapBuilder;
import com.google.idea.blaze.base.io.VirtualFileSystemProvider;
import com.google.idea.blaze.base.lang.buildfile.references.BuildReferenceManager;
import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.model.MockBlazeProjectDataBuilder;
import com.google.idea.blaze.base.model.MockBlazeProjectDataManager;
import com.google.idea.blaze.base.model.primitives.Label;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.projectview.ProjectViewManager;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.settings.Blaze;
import com.google.idea.blaze.base.settings.BlazeImportSettings;
import com.google.idea.blaze.base.settings.BlazeImportSettingsManager;
import com.google.idea.blaze.base.sync.BlazeSyncManager;
import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder;
import com.google.idea.blaze.base.sync.workspace.WorkspacePathResolver;
import com.intellij.mock.MockModule;
import com.intellij.mock.MockVirtualFile;
import com.intellij.openapi.editor.LazyRangeMarkerFactory;
import com.intellij.openapi.editor.impl.LazyRangeMarkerFactoryImpl;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import java.io.File;
import java.util.Map;
import javax.annotation.Nullable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;

/** Test cases for {@link BlazeBuildSystemService}. */
@RunWith(JUnit4.class)
public class BlazeBuildSystemServiceTest extends BlazeTestCase {
  WorkspaceRoot workspaceRoot = new WorkspaceRoot(new File("/"));
  Module module;
  BuildSystemService service;

  @Override
  protected void initTest(Container applicationServices, Container projectServices) {
    module = new MockModule(project, () -> {});

    mockBlazeImportSettings(projectServices); // For Blaze.isBlazeProject.
    createMocksForBuildProject(applicationServices);
    createMocksForSyncProject(projectServices);
    createMocksForAddDependency(applicationServices, projectServices);

    ExtensionPoint<BuildSystemService> extensionPoint =
        registerExtensionPoint(
            ExtensionPointName.create("com.android.project.buildSystemService"),
            BuildSystemService.class);
    extensionPoint.registerExtension(new BlazeBuildSystemService());

    service = BuildSystemService.getInstance(project);
  }

  @Test
  public void testIsBlazeBuildSystemService() {
    assertThat(service).isInstanceOf(BlazeBuildSystemService.class);
  }

  @Test
  public void testBuildProject() {
    service.buildProject(project);
    verify(BlazeBuildService.getInstance()).buildProject(project);
    verifyNoMoreInteractions(BlazeBuildService.getInstance());
  }

  @Test
  public void testSyncProject() {
    service.syncProject(project);
    verify(BlazeSyncManager.getInstance(project)).incrementalProjectSync();
    verifyNoMoreInteractions(BlazeSyncManager.getInstance(project));
  }

  @Test
  public void testAddDependencyWithBuildTargetPsi() throws Exception {
    PsiElement buildTargetPsi = mock(PsiElement.class);
    PsiFile psiFile = mock(PsiFile.class);

    BuildReferenceManager buildReferenceManager = BuildReferenceManager.getInstance(project);
    when(buildReferenceManager.resolveLabel(new Label("//foo:bar"))).thenReturn(buildTargetPsi);
    when(buildTargetPsi.getContainingFile()).thenReturn(psiFile);
    when(buildTargetPsi.getTextOffset()).thenReturn(1337);

    VirtualFile buildFile =
        VirtualFileSystemProvider.getInstance().getSystem().findFileByPath("/foo/BUILD");
    assertThat(buildFile).isNotNull();
    when(psiFile.getVirtualFile()).thenReturn(buildFile);

    String dependency = "com.android.foo:bar"; // Doesn't matter.

    service.addDependency(module, dependency);

    ArgumentCaptor<OpenFileDescriptor> descriptorCaptor =
        ArgumentCaptor.forClass(OpenFileDescriptor.class);
    verify(FileEditorManager.getInstance(project))
        .openTextEditor(descriptorCaptor.capture(), eq(true));
    OpenFileDescriptor descriptor = descriptorCaptor.getValue();
    assertThat(descriptor.getProject()).isEqualTo(project);
    assertThat(descriptor.getFile()).isEqualTo(buildFile);
    assertThat(descriptor.getOffset()).isEqualTo(1337);
    verifyNoMoreInteractions(FileEditorManager.getInstance(project));
  }

  @Test
  public void testAddDependencyWithoutBuildTargetPsi() throws Exception {
    // Can't find PSI for the target.
    when(BuildReferenceManager.getInstance(project).resolveLabel(new Label("//foo:bar")))
        .thenReturn(null);

    VirtualFile buildFile =
        VirtualFileSystemProvider.getInstance().getSystem().findFileByPath("/foo/BUILD");
    assertThat(buildFile).isNotNull();

    String dependency = "com.android.foo:bar"; // Doesn't matter.

    service.addDependency(module, dependency);

    verify(FileEditorManager.getInstance(project)).openFile(buildFile, true);
    verifyNoMoreInteractions(FileEditorManager.getInstance(project));
  }

  private void mockBlazeImportSettings(Container projectServices) {
    BlazeImportSettingsManager importSettingsManager = new BlazeImportSettingsManager(project);
    importSettingsManager.setImportSettings(
        new BlazeImportSettings("", "", "", "", "", Blaze.BuildSystem.Blaze));
    projectServices.register(BlazeImportSettingsManager.class, importSettingsManager);
  }

  private void createMocksForBuildProject(Container applicationServices) {
    applicationServices.register(BlazeBuildService.class, mock(BlazeBuildService.class));
  }

  private void createMocksForSyncProject(Container projectServices) {
    projectServices.register(ProjectViewManager.class, new MockProjectViewManager());
    projectServices.register(BlazeSyncManager.class, mock(BlazeSyncManager.class));
  }

  private void createMocksForAddDependency(
      Container applicationServices, Container projectServices) {
    projectServices.register(
        BlazeProjectDataManager.class,
        new MockBlazeProjectDataManager(createMockBlazeProjectData()));
    projectServices.register(FileEditorManager.class, mock(FileEditorManager.class));
    projectServices.register(BuildReferenceManager.class, mock(BuildReferenceManager.class));
    projectServices.register(LazyRangeMarkerFactory.class, mock(LazyRangeMarkerFactoryImpl.class));

    applicationServices.register(
        VirtualFileSystemProvider.class, new MockVirtualFileSystemProvider("/foo/BUILD"));

    AndroidResourceModuleRegistry moduleRegistry = new AndroidResourceModuleRegistry();
    moduleRegistry.put(
        module,
        AndroidResourceModule.builder(TargetKey.forPlainTarget(new Label("//foo:bar"))).build());
    projectServices.register(AndroidResourceModuleRegistry.class, moduleRegistry);
  }

  private BlazeProjectData createMockBlazeProjectData() {
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(
                TargetIdeInfo.builder()
                    .setLabel(new Label("//foo:bar"))
                    .setBuildFile(ArtifactLocation.builder().setRelativePath("foo/BUILD").build())
                    .build())
            .build();
    ArtifactLocationDecoder decoder = (location) -> new File("/", location.getRelativePath());
    return MockBlazeProjectDataBuilder.builder(workspaceRoot)
        .setTargetMap(targetMap)
        .setArtifactLocationDecoder(decoder)
        .build();
  }

  private static class MockProjectViewManager extends ProjectViewManager {
    private ProjectViewSet viewSet;

    public MockProjectViewManager() {
      this.viewSet = ProjectViewSet.builder().build();
    }

    @Nullable
    @Override
    public ProjectViewSet getProjectViewSet() {
      return viewSet;
    }

    @Nullable
    @Override
    public ProjectViewSet reloadProjectView(
        BlazeContext context, WorkspacePathResolver workspacePathResolver) {
      return viewSet;
    }
  }

  private static class MockFileSystem extends TempFileSystem {
    private Map<String, VirtualFile> files;

    public MockFileSystem(String... paths) {
      files = Maps.newHashMap();
      for (String path : paths) {
        files.put(path, new MockVirtualFile(path));
      }
    }

    @Override
    public VirtualFile findFileByPath(String path) {
      return files.get(path);
    }

    @Override
    public VirtualFile findFileByIoFile(File file) {
      return findFileByPath(file.getPath());
    }
  }

  private static class MockVirtualFileSystemProvider implements VirtualFileSystemProvider {

    private final LocalFileSystem fileSystem;

    MockVirtualFileSystemProvider(String... paths) {
      fileSystem = new MockFileSystem(paths);
    }

    @Override
    public LocalFileSystem getSystem() {
      return fileSystem;
    }
  }
}
