/*
 * Copyright 2012-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.python;

import static com.facebook.buck.rules.BuildableProperties.Kind.LIBRARY;

import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.rules.AbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.AbstractBuildable;
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.BuildableProperties;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.SrcsAttributeBuilder;
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.SymlinkFileStep;
import com.facebook.buck.util.BuckConstant;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;

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

import javax.annotation.Nullable;

public class PythonLibrary extends AbstractBuildable {

  private final static BuildableProperties OUTPUT_TYPE = new BuildableProperties(LIBRARY);
  private final BuildTarget buildTarget;
  // TODO(simons): Convert to using Paths
  private final ImmutableSortedSet<String> srcs;
  private final Path pythonPathDirectory;

  protected PythonLibrary(BuildRuleParams buildRuleParams,
                          ImmutableSortedSet<String> srcs) {
    Preconditions.checkArgument(!srcs.isEmpty(),
        "Must specify srcs for %s.",
        buildRuleParams.getBuildTarget());

    this.buildTarget = buildRuleParams.getBuildTarget();
    this.srcs = ImmutableSortedSet.copyOf(srcs);

    this.pythonPathDirectory = getPathToPythonPathDirectory();
  }

  @Nullable
  @Override
  public String getPathToOutputFile() {
    return null;
  }

  @Override
  public RuleKey.Builder appendDetailsToRuleKey(RuleKey.Builder builder) throws IOException {
    return builder.set("srcs", srcs);
  }

  private Path getPathToPythonPathDirectory() {
    return Paths.get(
        BuckConstant.GEN_DIR,
        buildTarget.getBasePath(),
        getPathUnderGenDirectory());
  }

  private String getPathUnderGenDirectory() {
    return "__pylib_" + buildTarget.getShortName();
  }

  public ImmutableSortedSet<String> getPythonSrcs() {
    return srcs;
  }

  @Override
  public Iterable<String> getInputsToCompareToOutput() {
    return srcs;
  }

  public Path getPythonPathDirectory() {
    return pythonPathDirectory;
  }

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

    // Copy all of the sources to a generated directory so that the generated directory can be
    // included as a $PYTHONPATH element. TODO(mbolin): Symlinks would be more efficient, but we
    // need to include this structure in the artifact, which is not guaranteed to be zip-friendly.
    commands.add(new MakeCleanDirectoryStep(pythonPathDirectory));

    ImmutableSortedSet.Builder<Path> directories = ImmutableSortedSet.naturalOrder();
    ImmutableList.Builder<Step> symlinkSteps = ImmutableList.builder();

    for (String src : srcs) {
      Path srcPath = Paths.get(src);
      Path targetPath = pythonPathDirectory.resolve(srcPath);

      directories.add(targetPath.getParent());
      symlinkSteps.add(
          new SymlinkFileStep(srcPath.toString(),
              targetPath.toString(),
              /* useAbsolutePaths */ false));

      Path pathToArtifact = Paths.get(getPathUnderGenDirectory()).resolve(srcPath);
      buildableContext.recordArtifact(pathToArtifact);
    }

    for (Path path : directories.build()) {
      commands.add(new MkdirStep(path));
    }

    commands.addAll(symlinkSteps.build());

    return commands.build();
  }

  @Override
  public BuildableProperties getProperties() {
    return OUTPUT_TYPE;
  }

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

  public static class Builder extends AbstractBuildable.Builder
      implements SrcsAttributeBuilder {
    protected ImmutableSortedSet.Builder<String> srcs = ImmutableSortedSet.naturalOrder();

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

    @Override
    public Builder addSrc(String src) {
      srcs.add(src);
      return this;
    }

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

    @Override
    protected PythonLibrary newBuildable(BuildRuleParams params, BuildRuleResolver resolver) {
      return new PythonLibrary(params, srcs.build());
    }
  }
}
