/*
 * Copyright 2015-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.go;

import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.Flavored;
import com.facebook.buck.parser.NoSuchBuildTargetException;
import com.facebook.buck.rules.AbstractDescriptionArg;
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.SourcePath;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.infer.annotation.SuppressFieldNotInitialized;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;

import java.util.List;

public class GoBinaryDescription implements Description<GoBinaryDescription.Arg>, Flavored {

  private static final BuildRuleType TYPE = BuildRuleType.of("go_binary");

  private final GoBuckConfig goBuckConfig;

  public GoBinaryDescription(GoBuckConfig goBuckConfig) {
    this.goBuckConfig = goBuckConfig;
  }

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

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

  @Override
  public boolean hasFlavors(ImmutableSet<Flavor> flavors) {
    return goBuckConfig.getPlatformFlavorDomain().containsAnyOf(flavors);
  }

  @Override
  public <A extends Arg> BuildRule createBuildRule(
      TargetGraph targetGraph,
      BuildRuleParams params,
      BuildRuleResolver resolver,
      A args) throws NoSuchBuildTargetException {
    GoPlatform platform = goBuckConfig.getPlatformFlavorDomain().getValue(params.getBuildTarget())
        .or(goBuckConfig.getDefaultPlatform());

    return GoDescriptors.createGoBinaryRule(
        params,
        resolver,
        goBuckConfig,
        args.srcs,
        args.compilerFlags.get(),
        args.assemblerFlags.get(),
        args.linkerFlags.get(),
        platform);
  }

  @SuppressFieldNotInitialized
  public static class Arg extends AbstractDescriptionArg {
    public ImmutableSet<SourcePath> srcs;
    public Optional<List<String>> compilerFlags;
    public Optional<List<String>> assemblerFlags;
    public Optional<List<String>> linkerFlags;
    public Optional<ImmutableSortedSet<BuildTarget>> deps;
  }
}

@@ -631,16 +631,58 @@
 ck.go;%0A%0A
+import com.facebook.buck.cxx.CxxPlatform;%0A
 import c
@@ -1138,24 +1138,89 @@
 escription;%0A
+import com.facebook.buck.rules.ImplicitDepsInferringDescription;%0A
 import com.f
@@ -1390,24 +1390,112 @@
 on.base.
-Optional
+Function;%0Aimport com.google.common.base.Optional;%0Aimport com.google.common.collect.ImmutableList
 ;%0Aimport
@@ -1589,16 +1589,43 @@
 edSet;%0A%0A
+import java.nio.file.Path;%0A
 import j
@@ -1683,16 +1683,20 @@
 plements
+%0A   
  Descrip
@@ -1725,16 +1725,83 @@
 on.Arg%3E,
+%0A    ImplicitDepsInferringDescription%3CGoBinaryDescription.Arg%3E,%0A   
  Flavore
@@ -2945,16 +2945,508 @@
 );%0A  %7D%0A%0A
+  @Override%0A  public Iterable%3CBuildTarget%3E findDepsForTargetFromConstructorArgs(%0A      BuildTarget buildTarget,%0A      Function%3COptional%3CString%3E, Path%3E cellRoots,%0A      Arg constructorArg) %7B%0A    ImmutableList.Builder%3CBuildTarget%3E targets = ImmutableList.builder();%0A%0A    // Add the C/C++ linker parse time deps.%0A    CxxPlatform cxxPlatform = goBuckConfig.getDefaultPlatform().getCxxPlatform().get();%0A    targets.addAll(cxxPlatform.getLd().getParseTimeDeps());%0A%0A    return targets.build();%0A  %7D%0A%0A
   @Suppr

Include cxx linker and parse time dep for Go.