/*
 * Copyright 2013-present Facebook, Inc.
 *
 * 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.facebook.buck.rules;

import com.facebook.buck.event.BuckEventBus;
import com.facebook.buck.event.LogEvent;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.util.BuckConstant;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Set;

/**
 * Utility for recording the paths to the output files generated by a build rule, as well as any
 * metadata about those output files. This data will be packaged up into an artifact that will be
 * stored in the cache. The metadata will also be written to disk so it can be read on a subsequent
 * build by a {@link OnDiskBuildInfo}.
 */
public class BuildInfoRecorder {

  private final BuildTarget buildTarget;
  private final Path pathToMetadataDirectory;
  private final ProjectFilesystem projectFilesystem;
  private final Map<String, String> metadataToWrite;
  private final RuleKey ruleKey;

  /**
   * Every value in this set is a path relative to the project root.
   */
  private final Set<Path> pathsToOutputFiles;

  BuildInfoRecorder(BuildTarget buildTarget,
      ProjectFilesystem projectFilesystem,
      RuleKey ruleKey,
      RuleKey rukeKeyWithoutDeps) {
    this.buildTarget = Preconditions.checkNotNull(buildTarget);
    this.pathToMetadataDirectory = BuildInfo.getPathToMetadataDirectory(buildTarget);
    this.projectFilesystem = Preconditions.checkNotNull(projectFilesystem);
    this.metadataToWrite = Maps.newHashMap();

    metadataToWrite.put(BuildInfo.METADATA_KEY_FOR_RULE_KEY,
        Preconditions.checkNotNull(ruleKey).toString());
    metadataToWrite.put(BuildInfo.METADATA_KEY_FOR_RULE_KEY_WITHOUT_DEPS,
        Preconditions.checkNotNull(rukeKeyWithoutDeps).toString());
    this.ruleKey = ruleKey;
    this.pathsToOutputFiles = Sets.newHashSet();
  }

  /**
   * Writes the metadata currently stored in memory to the directory returned by
   * {@link BuildInfo#getPathToMetadataDirectory(BuildTarget)}.
   */
  public void writeMetadataToDisk() throws IOException {
    projectFilesystem.rmdir(pathToMetadataDirectory.toString());
    projectFilesystem.mkdirs(pathToMetadataDirectory);

    for (Map.Entry<String, String> entry : metadataToWrite.entrySet()) {
      projectFilesystem.writeContentsToPath(
          entry.getValue(),
          pathToMetadataDirectory.resolve(entry.getKey()));
    }
  }

  /**
   * This key/value pair is stored in memory until {@link #writeMetadataToDisk()} is invoked.
   */
  public void addMetadata(String key, String value) {
    metadataToWrite.put(Preconditions.checkNotNull(key), Preconditions.checkNotNull(value));
  }

  /**
   * Creates a zip file of the metadata and recorded artifacts and stores it in the artifact cache.
   */
  public void performUploadToArtifactCache(ArtifactCache artifactCache, BuckEventBus eventBus) {
    // Skip all of this if caching is disabled. Although artifactCache.store() will be a noop,
    // building up the zip is wasted I/O.
    if (!artifactCache.isStoreSupported()) {
      return;
    }

    ImmutableSet<Path> pathsToIncludeInZip = ImmutableSet.<Path>builder()
        .addAll(Iterables.transform(metadataToWrite.keySet(),
            new Function<String, Path>() {
              @Override
              public Path apply(String key) {
                return pathToMetadataDirectory.resolve(key);
              }
            }))
        .addAll(pathsToOutputFiles)
        .build();
    File zip;
    try {
      zip = File.createTempFile(buildTarget.getFullyQualifiedName().replace('/', '_'), ".zip");
      projectFilesystem.createZip(pathsToIncludeInZip, zip);
    } catch (IOException e) {
      eventBus.post(LogEvent.info("Failed to create zip for %s containing:\n%s",
          buildTarget,
          Joiner.on('\n').join(ImmutableSortedSet.copyOf(pathsToIncludeInZip))));
      e.printStackTrace();
      return;
    }
    artifactCache.store(ruleKey, zip);
    zip.delete();
  }

  /**
   * Fetches the artifact associated with the {@link #buildTarget} for this class and writes it to
   * the specified {@code outputFile}.
   */
  public CacheResult fetchArtifactForBuildable(File outputFile, ArtifactCache artifactCache) {
    Preconditions.checkNotNull(outputFile);
    return artifactCache.fetch(ruleKey, outputFile);
  }

  /**
   * @param pathToArtifact Must be relative to the directory where the Buildable's
   *     generated files are to be written. The caller should not be concerned with the location
   *     of this directory.
   */
  public void recordArtifact(Path pathToArtifact) {
    Preconditions.checkNotNull(pathToArtifact);
    Path fullPath = Paths.get(BuckConstant.GEN_DIR, buildTarget.getBasePath(),
        pathToArtifact.toString());
    pathsToOutputFiles.add(fullPath);
  }
}
