/*
 * 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.sync.jdeps;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.idea.blaze.base.async.FutureUtil;
import com.google.idea.blaze.base.async.executor.BlazeExecutor;
import com.google.idea.blaze.base.filecache.FileDiffer;
import com.google.idea.blaze.base.ideinfo.ArtifactLocation;
import com.google.idea.blaze.base.ideinfo.JavaIdeInfo;
import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
import com.google.idea.blaze.base.ideinfo.TargetKey;
import com.google.idea.blaze.base.model.SyncState;
import com.google.idea.blaze.base.prefetch.PrefetchService;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.Scope;
import com.google.idea.blaze.base.scope.output.PrintOutput;
import com.google.idea.blaze.base.scope.scopes.TimingScope;
import com.google.idea.blaze.base.sync.workspace.ArtifactLocationDecoder;
import com.google.repackaged.devtools.build.lib.view.proto.Deps;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.Nullable;

/** Reads jdeps from the ide info result. */
public class JdepsFileReader {
  private static final Logger logger = Logger.getInstance(JdepsFileReader.class);

  static class JdepsState implements Serializable {
    private static final long serialVersionUID = 4L;
    private ImmutableMap<File, Long> fileState = null;
    private Map<File, TargetKey> fileToTargetMap = Maps.newHashMap();
    private Map<TargetKey, List<String>> targetToJdeps = Maps.newHashMap();
  }

  private static class Result {
    File file;
    TargetKey targetKey;
    List<String> dependencies;

    public Result(File file, TargetKey targetKey, List<String> dependencies) {
      this.file = file;
      this.targetKey = targetKey;
      this.dependencies = dependencies;
    }
  }

  /** Loads any updated jdeps files since the last invocation of this method. */
  @Nullable
  public JdepsMap loadJdepsFiles(
      Project project,
      BlazeContext parentContext,
      ArtifactLocationDecoder artifactLocationDecoder,
      Iterable<TargetIdeInfo> targetsToLoad,
      SyncState.Builder syncStateBuilder,
      @Nullable SyncState previousSyncState) {
    JdepsState oldState =
        previousSyncState != null ? previousSyncState.get(JdepsState.class) : null;
    JdepsState jdepsState =
        Scope.push(
            parentContext,
            (context) -> {
              context.push(new TimingScope("LoadJdepsFiles"));
              return doLoadJdepsFiles(
                  project, context, artifactLocationDecoder, oldState, targetsToLoad);
            });
    if (jdepsState == null) {
      return null;
    }
    syncStateBuilder.put(JdepsState.class, jdepsState);
    return targetKey -> jdepsState.targetToJdeps.get(targetKey);
  }

  private JdepsState doLoadJdepsFiles(
      Project project,
      BlazeContext context,
      ArtifactLocationDecoder artifactLocationDecoder,
      @Nullable JdepsState oldState,
      Iterable<TargetIdeInfo> targetsToLoad) {
    JdepsState state = new JdepsState();
    if (oldState != null) {
      state.targetToJdeps = Maps.newHashMap(oldState.targetToJdeps);
      state.fileToTargetMap = Maps.newHashMap(oldState.fileToTargetMap);
    }

    Map<File, TargetKey> fileToTargetMap = Maps.newHashMap();
    for (TargetIdeInfo target : targetsToLoad) {
      assert target != null;
      JavaIdeInfo javaIdeInfo = target.javaIdeInfo;
      if (javaIdeInfo != null) {
        ArtifactLocation jdepsFile = javaIdeInfo.jdepsFile;
        if (jdepsFile != null) {
          fileToTargetMap.put(artifactLocationDecoder.decode(jdepsFile), target.key);
        }
      }
    }

    List<File> updatedFiles = Lists.newArrayList();
    List<File> removedFiles = Lists.newArrayList();
    state.fileState =
        FileDiffer.updateFiles(
            oldState != null ? oldState.fileState : null,
            fileToTargetMap.keySet(),
            updatedFiles,
            removedFiles);

    ListenableFuture<?> fetchFuture =
        PrefetchService.getInstance().prefetchFiles(project, updatedFiles, true);
    if (!FutureUtil.waitForFuture(context, fetchFuture)
        .timed("FetchJdeps")
        .withProgressMessage("Reading jdeps files...")
        .run()
        .success()) {
      return null;
    }

    for (File removedFile : removedFiles) {
      TargetKey targetKey = state.fileToTargetMap.remove(removedFile);
      if (targetKey != null) {
        state.targetToJdeps.remove(targetKey);
      }
    }

    AtomicLong totalSizeLoaded = new AtomicLong(0);

    List<ListenableFuture<Result>> futures = Lists.newArrayList();
    for (File updatedFile : updatedFiles) {
      futures.add(
          submit(
              () -> {
                totalSizeLoaded.addAndGet(updatedFile.length());
                try (InputStream inputStream = new FileInputStream(updatedFile)) {
                  Deps.Dependencies dependencies = Deps.Dependencies.parseFrom(inputStream);
                  if (dependencies != null) {
                    List<String> dependencyStringList = Lists.newArrayList();
                    for (Deps.Dependency dependency : dependencies.getDependencyList()) {
                      // We only want explicit or implicit deps that were
                      // actually resolved by the compiler, not ones that are
                      // available for use in the same package
                      if (dependency.getKind() == Deps.Dependency.Kind.EXPLICIT
                          || dependency.getKind() == Deps.Dependency.Kind.IMPLICIT) {
                        dependencyStringList.add(dependency.getPath());
                      }
                    }
                    TargetKey targetKey = fileToTargetMap.get(updatedFile);
                    return new Result(updatedFile, targetKey, dependencyStringList);
                  }
                } catch (FileNotFoundException e) {
                  logger.info("Could not open jdeps file: " + updatedFile);
                }
                return null;
              }));
    }
    try {
      for (Result result : Futures.allAsList(futures).get()) {
        if (result != null) {
          state.fileToTargetMap.put(result.file, result.targetKey);
          state.targetToJdeps.put(result.targetKey, result.dependencies);
        }
      }
      context.output(
          PrintOutput.log(
              String.format(
                  "Loaded %d jdeps files, total size %dkB",
                  updatedFiles.size(), totalSizeLoaded.get() / 1024)));
    } catch (InterruptedException | ExecutionException e) {
      logger.error(e);
      return null;
    }
    return state;
  }

  private static <T> ListenableFuture<T> submit(Callable<T> callable) {
    return BlazeExecutor.getInstance().submit(callable);
  }
}
