/*
 * 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.cxx.CxxDescriptionEnhancer;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.ImmutableFlavor;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.Description;
import com.facebook.buck.rules.ImmutableBuildRuleType;
import com.facebook.buck.rules.Label;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.coercer.Either;
import com.facebook.infer.annotation.SuppressFieldNotInitialized;
import com.google.common.base.Optional;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;

public class AppleTestDescription implements Description<AppleTestDescription.Arg> {
  public static final BuildRuleType TYPE = ImmutableBuildRuleType.of("apple_test");

  /**
   * Flavors for the additional generated build rules.
   */
  private static final Flavor LIBRARY_FLAVOR = ImmutableFlavor.of("apple-test-library");
  private static final Flavor BUNDLE_FLAVOR = ImmutableFlavor.of("apple-test-bundle");

  private final AppleLibraryDescription appleLibraryDescription;

  public AppleTestDescription(AppleLibraryDescription description) {
    appleLibraryDescription = description;
  }

  @Override
  public BuildRuleType getBuildRuleType() {
    return TYPE;
  }

  @Override
  public Arg createUnpopulatedConstructorArg() {
    return new Arg();
  }

  @Override
  public <A extends Arg> AppleTest createBuildRule(
      BuildRuleParams params,
      BuildRuleResolver resolver,
      A args) {
    BuildRule library = appleLibraryDescription.createBuildRule(
        params.copyWithChanges(
            AppleLibraryDescription.TYPE,
            BuildTarget.builder(params.getBuildTarget())
                .addFlavors(LIBRARY_FLAVOR)
                .addFlavors(CxxDescriptionEnhancer.SHARED_FLAVOR)
                .addFlavors(ImmutableFlavor.of("default"))
                .build(),
            Suppliers.ofInstance(params.getDeclaredDeps()),
            Suppliers.ofInstance(params.getExtraDeps())),
        resolver,
        args);
    SourcePathResolver sourcePathResolver = new SourcePathResolver(resolver);
    AppleBundle bundle = new AppleBundle(
        params.copyWithChanges(
            AppleBundleDescription.TYPE,
            BuildTarget.builder(params.getBuildTarget()).addFlavors(BUNDLE_FLAVOR).build(),
            Suppliers.ofInstance(ImmutableSortedSet.of(library)),
            Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())),
        sourcePathResolver,
        args.extension,
        args.infoPlist,
        library,
        args.xcodeProductType);
    return new AppleTest(
        params.copyWithDeps(
            Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of(bundle)),
            Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())),
        sourcePathResolver,
        bundle,
        args.contacts.get(),
        args.labels.get(),
        ImmutableSet.<BuildRule>of());
  }

  @SuppressFieldNotInitialized
  public static class Arg extends AppleNativeTargetDescriptionArg implements HasAppleBundleFields {
    public Optional<ImmutableSortedSet<String>> contacts;
    public Optional<ImmutableSortedSet<Label>> labels;
    public Optional<ImmutableSortedSet<BuildTarget>> deps;
    public Optional<Boolean> canGroup;

    // Bundle related fields.
    public Either<AppleBundleExtension, String> extension;
    public Optional<SourcePath> infoPlist;
    public Optional<String> xcodeProductType;

    @Override
    public Either<AppleBundleExtension, String> getExtension() {
      return extension;
    }

    @Override
    public Optional<SourcePath> getInfoPlist() {
      return infoPlist;
    }

    @Override
    public Optional<String> getXcodeProductType() {
      return xcodeProductType;
    }

    public boolean canGroup() {
      return canGroup.or(false);
    }
  }
}

@@ -762,32 +762,73 @@
 k.model.Flavor;%0A
+import com.facebook.buck.model.Flavored;%0A
 import com.faceb
@@ -1459,25 +1459,157 @@
 on.base.
-Suppliers
+Predicate;%0Aimport com.google.common.base.Predicates;%0Aimport com.google.common.base.Suppliers;%0Aimport com.google.common.collect.FluentIterable
 ;%0Aimport
@@ -1703,16 +1703,39 @@
 edSet;%0A%0A
+import java.util.Set;%0A%0A
 public c
@@ -1808,16 +1808,26 @@
 ion.Arg%3E
+, Flavored
  %7B%0A  pub
@@ -2150,16 +2150,225 @@
 dle%22);%0A%0A
+  private static final Set%3CFlavor%3E SUPPORTED_FLAVORS = ImmutableSet.of(%0A      LIBRARY_FLAVOR, BUNDLE_FLAVOR);%0A%0A  private static final Predicate%3CFlavor%3E IS_SUPPORTED_FLAVOR = Predicates.in(SUPPORTED_FLAVORS);%0A%0A
   privat
@@ -2704,24 +2704,227 @@
 Arg();%0A  %7D%0A%0A
+  @Override%0A  public boolean hasFlavors(ImmutableSet%3CFlavor%3E flavors) %7B%0A    return FluentIterable.from(flavors).allMatch(IS_SUPPORTED_FLAVOR) %7C%7C%0A        appleLibraryDescription.hasFlavors(flavors);%0A  %7D%0A%0A
   @Override%0A
@@ -3365,67 +3365,8 @@
 OR)%0A
-                .addFlavors(ImmutableFlavor.of(%22default%22))%0A
     

Make AppleTestDescription implement Flavored