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

import com.facebook.buck.io.DirectoryTraverser;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.rules.AbstractBuildRule;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRules;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.CopyStep;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;

import java.nio.file.Path;
import java.util.Map;

import javax.annotation.Nullable;

/**
 * Copies the image, sound, NIB/XIB, and other resources
 * of an iOS or OS X library.
 * <p>
 * Example rule:
 * <pre>
 * apple_resource(
 *   name = 'res',
 *   dirs = ['MyLibrary.bundle'],
 *   files = glob(['Resources/**']),
 *   variants = {
 *     'Resources/Localizable.strings' : {
 *       'en' : 'Resources/en.lproj/Localizable.strings',
 *       'fr' : 'Resources/fr.lproj/Localizable.strings',
 *     },
 *   },
 * )
 * </pre>
 */
public class AppleResource extends AbstractBuildRule {

  private final DirectoryTraverser directoryTraverser;
  private final ImmutableSortedSet<Path> dirs;
  private final ImmutableSortedSet<SourcePath> files;
  private final ImmutableMap<String, ImmutableMap<String, SourcePath>> variants;
  private final Path outputDirectory;

  AppleResource(
      BuildRuleParams params,
      SourcePathResolver resolver,
      DirectoryTraverser directoryTraverser,
      AppleResourceDescription.Arg args) {
    super(params, resolver);
    this.directoryTraverser = directoryTraverser;
    this.dirs = ImmutableSortedSet.copyOf(args.dirs);
    this.files = ImmutableSortedSet.copyOf(args.files);

    if (args.variants.isPresent()) {
      Map<String, Map<String, SourcePath>> variants = args.variants.get();
      ImmutableMap.Builder<String, ImmutableMap<String, SourcePath>> variantsBuilder =
          ImmutableMap.builder();
      for (String path : variants.keySet()) {
        variantsBuilder.put(path, ImmutableMap.copyOf(variants.get(path)));
      }
      this.variants = variantsBuilder.build();
    } else {
      this.variants = ImmutableMap.of();
    }

    BuildTarget target = params.getBuildTarget();
    // TODO(user): This is hokey, just a hack to get started.
    // TODO(grp): Support copying into a bundle's resources subdirectory.
    this.outputDirectory = BuildTargets.getBinPath(target, "%s.app");
  }

  /**
   * Returns the set of directories to recursively copy for this resource rule.
   */
  public ImmutableSortedSet<Path> getDirs() {
    return dirs;
  }

  /**
   * Returns the set of files to copy for this resource rule.
   */
  public ImmutableSortedSet<SourcePath> getFiles() {
    return files;
  }

  @Override
  public ImmutableCollection<Path> getInputsToCompareToOutput() {
    ImmutableSortedSet.Builder<Path> inputsToConsiderForCachingPurposes = ImmutableSortedSet
        .naturalOrder();

    for (Path dir : dirs) {
      BuildRules.addInputsToSortedSet(
          dir,
          inputsToConsiderForCachingPurposes,
          directoryTraverser);
    }

    for (String virtualPathName : variants.keySet()) {
      Map<String, SourcePath> variant =
          Preconditions.checkNotNull(variants.get(virtualPathName));
      inputsToConsiderForCachingPurposes.addAll(
          getResolver().filterInputsToCompareToOutput(variant.values()));
    }

    inputsToConsiderForCachingPurposes.addAll(getResolver().filterInputsToCompareToOutput(files));
    return inputsToConsiderForCachingPurposes.build();
  }

  @Override
  public RuleKey.Builder appendDetailsToRuleKey(RuleKey.Builder builder) {
    return builder;
  }

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

  @Override
  public ImmutableList<Step> getBuildSteps(
      BuildContext context,
      BuildableContext buildableContext) {

    ImmutableList.Builder<Step> steps = ImmutableList.builder();

    steps.add(new MakeCleanDirectoryStep(outputDirectory));

    for (Path dir : dirs) {
      steps.add(
          CopyStep.forDirectory(
              dir,
              outputDirectory,
              CopyStep.DirectoryMode.DIRECTORY_AND_CONTENTS));
    }

    for (SourcePath file : files) {
      Path path = getResolver().getPath(file);
      steps.add(CopyStep.forFile(path, outputDirectory.resolve(path.getFileName())));
    }

    // TODO(grp): Support copying variant resources like Xcode.

    return steps.build();
  }
}
