/*
 * Copyright 2014-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.zip;

import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.rules.AbstractBuildRule;
import com.facebook.buck.rules.AddToRuleKey;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.step.fs.MkdirStep;
import com.facebook.buck.step.fs.RmStep;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;

import java.nio.file.Path;

public class Zip extends AbstractBuildRule {

  @AddToRuleKey(stringify = true)
  private final Path output;
  @AddToRuleKey
  private final ImmutableSortedSet<SourcePath> sources;
  private final Path scratchDir;

  public Zip(
      BuildRuleParams params,
      SourcePathResolver resolver,
      String outputName,
      ImmutableSortedSet<SourcePath> sources) {
    super(params, resolver);
    this.sources = Preconditions.checkNotNull(sources);

    this.output = BuildTargets.getGenPath(getProjectFilesystem(), getBuildTarget(), outputName);
    this.scratchDir =
        BuildTargets.getScratchPath(getProjectFilesystem(), getBuildTarget(), "%s.zip.scratch");
  }

  @Override
  public ImmutableList<Step> getBuildSteps(
      BuildContext context,
      BuildableContext buildableContext) {
    ImmutableList.Builder<Step> steps = ImmutableList.builder();

    steps.add(new RmStep(getProjectFilesystem(), output, true));
    steps.add(new MkdirStep(getProjectFilesystem(), output.getParent()));
    steps.add(new MakeCleanDirectoryStep(getProjectFilesystem(), scratchDir));

    SrcZipAwareFileBundler bundler = new SrcZipAwareFileBundler(getBuildTarget());
    bundler.copy(getProjectFilesystem(), getResolver(), steps, scratchDir, sources);

    steps.add(
        new ZipStep(
            getProjectFilesystem(),
            output,
            ImmutableSortedSet.of(),
            /* junk paths */ false,
            ZipCompressionLevel.DEFAULT_COMPRESSION_LEVEL,
            scratchDir));

    buildableContext.recordArtifact(output);

    return steps.build();
  }

  @Override
  public Path getPathToOutput() {
    return output;
  }
}

@@ -677,16 +677,62 @@
 argets;%0A
+import com.facebook.buck.model.HasOutputName;%0A
 import c
@@ -1236,53 +1236,8 @@
 ep;%0A
-import com.google.common.base.Preconditions;%0A
 impo
@@ -1405,16 +1405,41 @@
 ildRule 
+implements HasOutputName 
 %7B%0A%0A  @Ad
@@ -1452,26 +1452,8 @@
 eKey
-(stringify = true)
 %0A  p
@@ -1469,19 +1469,19 @@
 nal 
-Path output
+String name
 ;%0A  
@@ -1553,41 +1553,8 @@
 ces;
-%0A  private final Path scratchDir;
 %0A%0A  
@@ -1745,55 +1745,26 @@
 his.
-sources = Preconditions.checkNotNull(sources);%0A
+name = outputName;
 %0A   
@@ -1773,125 +1773,71 @@
 his.
+s
 ou
-tput = BuildTargets.getGenPath(getProjectFilesystem(), getBuildTarget(), outputName);%0A    this.scratchDir =%0A       
+rces = sources;%0A  %7D%0A%0A  private Path getOutput() %7B%0A    return
  Bui
@@ -1853,15 +1853,11 @@
 .get
-Scratch
+Gen
 Path
@@ -1906,21 +1906,37 @@
  %22%25s
-.zip.scratch%22
+%22)%0A        .resolve(this.name
 );%0A 
@@ -2062,24 +2062,176 @@
 eContext) %7B%0A
+%0A    Path output = getOutput();%0A    Path scratchDir =%0A        BuildTargets.getScratchPath(getProjectFilesystem(), getBuildTarget(), %22%25s.zip.scratch%22);%0A%0A
     Immutabl
@@ -3061,18 +3061,92 @@
 urn 
-o
+getO
 utput
+()
 ;%0A  %7D%0A
+%0A  @Override%0A  public String getOutputName() %7B%0A    return name;%0A  %7D%0A%0A
 %7D%0A

use for target name when forming output directory