/*
 * 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.java.libraries;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.idea.blaze.base.filecache.FileCache;
import com.google.idea.blaze.base.filecache.FileDiffer;
import com.google.idea.blaze.base.io.FileSizeScanner;
import com.google.idea.blaze.base.model.BlazeLibrary;
import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.prefetch.FetchExecutor;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.output.PrintOutput;
import com.google.idea.blaze.base.settings.BlazeImportSettings;
import com.google.idea.blaze.base.settings.BlazeImportSettingsManager;
import com.google.idea.blaze.base.sync.BlazeSyncParams;
import com.google.idea.blaze.base.sync.BlazeSyncParams.SyncMode;
import com.google.idea.blaze.base.sync.data.BlazeDataStorage;
import com.google.idea.blaze.base.sync.libraries.BlazeLibraryCollector;
import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder;
import com.google.idea.blaze.java.settings.BlazeJavaUserSettings;
import com.google.idea.blaze.java.sync.model.BlazeJarLibrary;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/** Local cache of the jars referenced by the project. */
public class JarCache {
  private static final Logger logger = Logger.getInstance(JarCache.class);

  private final Project project;
  private final BlazeImportSettings importSettings;
  private final File cacheDir;
  private boolean enabled;
  @Nullable private BiMap<File, String> sourceFileToCacheKey = null;

  public static JarCache getInstance(Project project) {
    return ServiceManager.getService(project, JarCache.class);
  }

  public JarCache(Project project) {
    this.project = project;
    this.importSettings = BlazeImportSettingsManager.getInstance(project).getImportSettings();
    this.cacheDir = getCacheDir();
  }

  public void onSync(
      BlazeContext context,
      ProjectViewSet projectViewSet,
      BlazeProjectData projectData,
      BlazeSyncParams.SyncMode syncMode) {
    Collection<BlazeLibrary> libraries =
        BlazeLibraryCollector.getLibraries(projectViewSet, projectData);
    boolean fullRefresh = syncMode == SyncMode.FULL;
    boolean removeMissingFiles = syncMode == SyncMode.INCREMENTAL;
    boolean enabled = updateEnabled();

    if (!enabled || fullRefresh) {
      clearCache();
    }
    if (!enabled) {
      return;
    }

    boolean attachAllSourceJars = BlazeJavaUserSettings.getInstance().getAttachSourcesByDefault();
    SourceJarManager sourceJarManager = SourceJarManager.getInstance(project);

    List<BlazeJarLibrary> jarLibraries =
        libraries
            .stream()
            .filter(library -> library instanceof BlazeJarLibrary)
            .map(library -> (BlazeJarLibrary) library)
            .collect(Collectors.toList());

    ArtifactLocationDecoder artifactLocationDecoder = projectData.artifactLocationDecoder;
    BiMap<File, String> sourceFileToCacheKey = HashBiMap.create(jarLibraries.size());
    for (BlazeJarLibrary library : jarLibraries) {
      File jarFile =
          artifactLocationDecoder.decode(library.libraryArtifact.jarForIntellijLibrary());
      sourceFileToCacheKey.put(jarFile, cacheKeyForJar(jarFile));

      boolean attachSourceJar =
          attachAllSourceJars || sourceJarManager.hasSourceJarAttached(library.key);
      if (attachSourceJar && library.libraryArtifact.sourceJar != null) {
        File srcJarFile = artifactLocationDecoder.decode(library.libraryArtifact.sourceJar);
        sourceFileToCacheKey.put(srcJarFile, cacheKeyForSourceJar(srcJarFile));
      }
    }

    this.sourceFileToCacheKey = sourceFileToCacheKey;
    refresh(context, removeMissingFiles);
  }

  public boolean isEnabled() {
    return enabled;
  }

  private boolean updateEnabled() {
    this.enabled =
        BlazeJavaUserSettings.getInstance().getUseJarCache()
            && !ApplicationManager.getApplication().isUnitTestMode();
    return enabled;
  }

  /** Refreshes any updated files in the cache. Does not add or removes any files */
  public void refresh() {
    refresh(null, false);
  }

  private void refresh(@Nullable BlazeContext context, boolean removeMissingFiles) {
    if (!enabled || sourceFileToCacheKey == null) {
      return;
    }

    // Ensure the cache dir exists
    if (!cacheDir.exists()) {
      if (!cacheDir.mkdirs()) {
        logger.error("Could not create jar cache directory");
        return;
      }
    }

    // Discover state of source jars
    ImmutableMap<File, Long> sourceFileTimestamps =
        FileDiffer.readFileState(sourceFileToCacheKey.keySet());
    if (sourceFileTimestamps == null) {
      return;
    }
    ImmutableMap.Builder<String, Long> sourceFileCacheKeyToTimestamp = ImmutableMap.builder();
    for (Map.Entry<File, Long> entry : sourceFileTimestamps.entrySet()) {
      String cacheKey = sourceFileToCacheKey.get(entry.getKey());
      sourceFileCacheKeyToTimestamp.put(cacheKey, entry.getValue());
    }

    // Discover current on-disk cache state
    File[] cacheFiles = cacheDir.listFiles();
    assert cacheFiles != null;
    ImmutableMap<File, Long> cacheFileTimestamps =
        FileDiffer.readFileState(Lists.newArrayList(cacheFiles));
    if (cacheFileTimestamps == null) {
      return;
    }
    ImmutableMap.Builder<String, Long> cachedFileCacheKeyToTimestamp = ImmutableMap.builder();
    for (Map.Entry<File, Long> entry : cacheFileTimestamps.entrySet()) {
      String cacheKey = entry.getKey().getName(); // Cache key == file name
      cachedFileCacheKeyToTimestamp.put(cacheKey, entry.getValue());
    }

    List<String> updatedFiles = Lists.newArrayList();
    List<String> removedFiles = Lists.newArrayList();
    FileDiffer.diffState(
        cachedFileCacheKeyToTimestamp.build(),
        sourceFileCacheKeyToTimestamp.build(),
        updatedFiles,
        removedFiles);

    ListeningExecutorService executor = FetchExecutor.EXECUTOR;
    List<ListenableFuture<?>> futures = Lists.newArrayList();
    Map<String, File> cacheKeyToSourceFile = sourceFileToCacheKey.inverse();
    for (String cacheKey : updatedFiles) {
      File sourceFile = cacheKeyToSourceFile.get(cacheKey);
      File cacheFile = cacheFileForKey(cacheKey);
      futures.add(
          executor.submit(
              () -> {
                try {
                  Files.copy(
                      Paths.get(sourceFile.getPath()),
                      Paths.get(cacheFile.getPath()),
                      StandardCopyOption.REPLACE_EXISTING,
                      StandardCopyOption.COPY_ATTRIBUTES);
                } catch (IOException e) {
                  logger.warn(e);
                }
              }));
    }

    if (removeMissingFiles) {
      for (String cacheKey : removedFiles) {
        File cacheFile = cacheFileForKey(cacheKey);
        futures.add(
            executor.submit(
                () -> {
                  try {
                    Files.deleteIfExists(Paths.get(cacheFile.getPath()));
                  } catch (IOException e) {
                    logger.warn(e);
                  }
                }));
      }
    }

    try {
      Futures.allAsList(futures).get();
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      logger.warn(e);
    } catch (ExecutionException e) {
      logger.error(e);
    }
    if (context != null && updatedFiles.size() > 0) {
      context.output(PrintOutput.log(String.format("Copied %d jars", updatedFiles.size())));
    }
    if (context != null && removedFiles.size() > 0 && removeMissingFiles) {
      context.output(PrintOutput.log(String.format("Removed %d jars", removedFiles.size())));
    }
    if (context != null) {
      try {
        File[] finalCacheFiles = cacheDir.listFiles();
        assert finalCacheFiles != null;
        ImmutableMap<File, Long> cacheFileSizes =
            FileSizeScanner.readFilesizes(Lists.newArrayList(finalCacheFiles));
        Long total =
            cacheFileSizes.values().stream().reduce((size1, size2) -> size1 + size2).orElse(0L);
        context.output(
            PrintOutput.log(
                String.format(
                    "Total Jar Cache size: %d kB (%d files)",
                    total / 1024, finalCacheFiles.length)));
      } catch (Exception e) {
        logger.warn("Could not determine cache size", e);
      }
    }
  }

  private void clearCache() {
    if (cacheDir.exists()) {
      File[] cacheFiles = cacheDir.listFiles();
      if (cacheFiles != null) {
        FileUtil.asyncDelete(Lists.newArrayList(cacheFiles));
      }
    }
    sourceFileToCacheKey = null;
  }

  /** Gets the cached file for a jar. If it doesn't exist, we return the file from the library. */
  public File getCachedJar(ArtifactLocationDecoder decoder, BlazeJarLibrary library) {
    File file = decoder.decode(library.libraryArtifact.jarForIntellijLibrary());
    if (!enabled || sourceFileToCacheKey == null) {
      return file;
    }
    String cacheKey = sourceFileToCacheKey.get(file);
    if (cacheKey == null) {
      return file;
    }
    return cacheFileForKey(cacheKey);
  }

  /** Gets the cached file for a source jar. */
  @Nullable
  public File getCachedSourceJar(ArtifactLocationDecoder decoder, BlazeJarLibrary library) {
    if (library.libraryArtifact.sourceJar == null) {
      return null;
    }
    File file = decoder.decode(library.libraryArtifact.sourceJar);
    if (!enabled || sourceFileToCacheKey == null) {
      return file;
    }
    String cacheKey = sourceFileToCacheKey.get(file);
    if (cacheKey == null) {
      return file;
    }
    return cacheFileForKey(cacheKey);
  }

  private static String cacheKeyInternal(File jar) {
    int parentHash = jar.getParent().hashCode();
    return FileUtil.getNameWithoutExtension(jar) + "_" + Integer.toHexString(parentHash);
  }

  private static String cacheKeyForJar(File jar) {
    return cacheKeyInternal(jar) + ".jar";
  }

  private static String cacheKeyForSourceJar(File srcjar) {
    return cacheKeyInternal(srcjar) + "-src.jar";
  }

  private File cacheFileForKey(String key) {
    return new File(cacheDir, key);
  }

  private File getCacheDir() {
    return new File(BlazeDataStorage.getProjectDataDir(importSettings), "libraries");
  }

  static class FileCacheAdapter implements FileCache {
    @Override
    public String getName() {
      return "Jar Cache";
    }

    @Override
    public void onSync(
        Project project,
        BlazeContext context,
        ProjectViewSet projectViewSet,
        BlazeProjectData projectData,
        BlazeSyncParams.SyncMode syncMode) {
      getInstance(project).onSync(context, projectViewSet, projectData, syncMode);
    }

    @Override
    public void refreshFiles(Project project) {
      getInstance(project).refresh();
    }
  }
}
