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

import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.rules.AbstractBuildRuleBuilder;
import com.facebook.buck.rules.AbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.BinaryBuildRule;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.DoNotUseAbstractBuildable;
import com.facebook.buck.rules.ResourcesAttributeBuilder;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePaths;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.util.BuckConstant;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

public class ShBinaryRule extends DoNotUseAbstractBuildable implements BinaryBuildRule {

  private final Path main;
  private final ImmutableSet<SourcePath> resources;

  /** The path where the output will be written. */
  private final Path output;

  protected ShBinaryRule(BuildRuleParams buildRuleParams,
      Path main,
      ImmutableSet<SourcePath> resources) {
    super(buildRuleParams);
    this.main = Preconditions.checkNotNull(main);
    this.resources = Preconditions.checkNotNull(resources);

    BuildTarget target = buildRuleParams.getBuildTarget();
    this.output = Paths.get(String.format("%s/%s%s.sh",
        BuckConstant.GEN_DIR,
        target.getBasePathWithSlash(),
        target.getShortName()));
  }

  @Override
  public Iterable<String> getInputsToCompareToOutput() {
    return Iterables.concat(ImmutableList.of(main.toString()),
        SourcePaths.filterInputsToCompareToOutput(resources));
  }

  @Override
  public List<Step> getBuildSteps(BuildContext context, BuildableContext buildableContext)
      throws IOException {
    MakeCleanDirectoryStep mkdir = new MakeCleanDirectoryStep(output.getParent().toString());

    // Generate an .sh file that builds up an environment and invokes the user's script.
    // This generated .sh file will be returned by getExecutableCommand().
    GenerateShellScriptStep generateShellScript = new GenerateShellScriptStep(
        Paths.get(getBuildTarget().getBasePath()),
        main,
        SourcePaths.toPaths(resources, context),
        output);

    return ImmutableList.of(mkdir, generateShellScript);
  }

  @Override
  public BuildRuleType getType() {
    return BuildRuleType.SH_BINARY;
  }

  @Override
  public String getPathToOutputFile() {
    return output.toString();
  }

  @Override
  public String getExecutableCommand(ProjectFilesystem projectFilesystem) {
    return projectFilesystem.getFileForRelativePath(output.toString()).getAbsolutePath();
  }

  public static Builder newShBinaryBuilder(AbstractBuildRuleBuilderParams params) {
    return new Builder(params);
  }

  public static class Builder extends AbstractBuildRuleBuilder<ShBinaryRule>
      implements ResourcesAttributeBuilder {

    private Path main;
    private ImmutableSet.Builder<SourcePath> resources = ImmutableSet.builder();

    protected Builder(AbstractBuildRuleBuilderParams params) {
      super(params);
    }

    @Override
    public ShBinaryRule build(BuildRuleResolver ruleResolver) {
      BuildRuleParams params = createBuildRuleParams(ruleResolver);
      return new ShBinaryRule(params,
          main,
          resources.build());
    }

    public Builder setMain(Path main) {
      this.main = main;
      return this;
    }

    @Override
    public Builder addResource(SourcePath relativePathToResource) {
      resources.add(relativePathToResource);
      return this;
    }
  }
}

@@ -2366,36 +2366,9 @@
 get(
-String.format(%22%25s/%25s%25s.sh%22,
 %0A
+
     
@@ -2423,19 +2423,55 @@
 Path
-WithSlash()
+(),%0A        %22__%22 + target.getShortName() + %22__%22
 ,%0A  
@@ -2497,17 +2497,24 @@
 rtName()
-)
+ + %22.sh%22
 );%0A  %7D%0A%0A

Fix the output path for sh_binary.