// 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.devtools.build.lib.packages;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Interner;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.concurrent.BlazeInterners;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.Map;
import java.util.Objects;
import net.starlark.java.eval.Module;

/**
 * A SkyValue that contains the result of the parsing of one part of the WORKSPACE file. The parsing
 * of the WORKSPACE file is split before each series of load statement because we need to resolve
 * repositories before being able to load from those repositories.
 */
public class WorkspaceFileValue implements SkyValue {
  public static final SkyFunctionName WORKSPACE_FILE =
      SkyFunctionName.createHermetic("WORKSPACE_FILE");

  /** Argument for the SkyKey to request a WorkspaceFileValue. */
  @Immutable
  @AutoCodec
  public static class WorkspaceFileKey implements SkyKey {
    private static final Interner<WorkspaceFileKey> interner = BlazeInterners.newWeakInterner();

    private final RootedPath path;
    private final int idx;

    private WorkspaceFileKey(RootedPath path, int idx) {
      this.path = path;
      this.idx = idx;
    }

    @AutoCodec.VisibleForSerialization
    @AutoCodec.Instantiator
    static WorkspaceFileKey create(RootedPath path, int idx) {
      return interner.intern(new WorkspaceFileKey(path, idx));
    }

    public RootedPath getPath() {
      return path;
    }

    public int getIndex() {
      return idx;
    }

    @Override
    public SkyFunctionName functionName() {
      return WORKSPACE_FILE;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) {
        return true;
      }
      if (!(obj instanceof WorkspaceFileKey)) {
        return false;
      }
      WorkspaceFileKey other = (WorkspaceFileKey) obj;
      return Objects.equals(path, other.path) && idx == other.idx;
    }

    @Override
    public int hashCode() {
      return Objects.hash(path.hashCode(), idx);
    }

    @Override
    public String toString() {
      return path + ", " + idx;
    }
  }

  private final Package pkg;
  private final int idx;
  private final RootedPath path;
  private final boolean hasNext;
  private final ImmutableMap<String, Object> bindings;
  private final ImmutableMap<String, Module> loadedModules;
  private final ImmutableMap<String, Integer> loadToChunkMap;
  private final ImmutableMap<RepositoryName, ImmutableMap<String, RepositoryName>>
      repositoryMapping;

  /**
   * Create a WorkspaceFileValue containing the various values necessary to compute the split
   * WORKSPACE file.
   *
   * @param pkg Package built by agreggating all parts of the split WORKSPACE file up to this one.
   * @param loadedModules modules loaded by load statements in chunks of the WORKSPACE file up to
   *     this one.
   * @param loadToChunkMap Map of all load statements encountered so far to the chunk they initially
   *     appeared in.
   * @param bindings List of top-level variable bindings from the all parts of the split WORKSPACE
   *     file up to this one. The key is the name of the bindings and the value is the actual
   *     object.
   * @param path The rooted path to workspace file to parse.
   * @param idx The index of this part of the split WORKSPACE file (0 for the first one, 1 for the
   *     second one and so on).
   * @param hasNext Is there a next part in the WORKSPACE file or this part the last one?
   */
  public WorkspaceFileValue(
      Package pkg,
      Map<String, Module> loadedModules,
      Map<String, Integer> loadToChunkMap,
      Map<String, Object> bindings,
      RootedPath path,
      int idx,
      boolean hasNext) {
    this.pkg = Preconditions.checkNotNull(pkg);
    this.idx = idx;
    this.path = path;
    this.hasNext = hasNext;
    this.bindings = ImmutableMap.copyOf(bindings);
    this.loadedModules = ImmutableMap.copyOf(loadedModules);
    this.loadToChunkMap = ImmutableMap.copyOf(loadToChunkMap);
    this.repositoryMapping = pkg.getExternalPackageRepositoryMappings();
  }

  /**
   * Returns the package. This package may contain errors, in which case the caller should throw
   * a {@link BuildFileContainsErrorsException}.
   */
  public Package getPackage() {
    return pkg;
  }

  @Override
  public String toString() {
    return "<WorkspaceFileValue path=" + path + " idx=" + idx + ">";
  }

  /**
   * Creates a Key for the WorkspaceFileFunction. The path to the workspace file is specified by
   * {@code path}. This key will ask WorkspaceFileFunction to get the {@code idx+1}-th part of the
   * workspace file (so idx = 0 represents the first part, idx = 1, the second part, etc...).
   */
  public static WorkspaceFileKey key(RootedPath path, int idx) {
    return WorkspaceFileKey.create(path, idx);
  }

  public static WorkspaceFileKey key(RootedPath path) {
    return key(path, 0);
  }

  /**
   * Get the key for the next WorkspaceFileValue or null if this value is the last part of the
   * workspace file.
   */
  public SkyKey next() {
    if (hasNext) {
      return key(path, idx + 1);
    } else {
      return null;
    }
  }

  /**
   * The workspace file parsing is cut in several parts and this function returns the index of the
   * part of the workspace file that this value holds. For the first part, this index will be 0, for
   * the second part, it will be 1 and so on.
   */
  public int getIndex() {
    return idx;
  }

  /**
   * The workspace file parsing is cut in several parts and this function returns true if there is
   * a part following the part holds by this value (or false if this is the last part of the
   * WORKSPACE file.
   *
   * <p>This method is public for serialization of the WorkspaceFileValue, #next() should be used
   * to iterate instead of this method.
   */
  public boolean hasNext() {
    return hasNext;
  }

  public RootedPath getPath() {
    return path;
  }

  public ImmutableMap<String, Object> getBindings() {
    return bindings;
  }

  public ImmutableMap<String, Module> getLoadedModules() {
    return loadedModules;
  }

  public ImmutableMap<String, Integer> getLoadToChunkMap() {
    return loadToChunkMap;
  }

  public ImmutableMap<RepositoryName, ImmutableMap<String, RepositoryName>> getRepositoryMapping() {
    return repositoryMapping;
  }
}
