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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.facebook.buck.cli.FakeBuckConfig;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.ImmutableFlavor;
import com.facebook.buck.python.PythonLibrary;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleParamsFactory;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.FakeBuildRule;
import com.facebook.buck.rules.FakeBuildRuleParamsBuilder;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.TestSourcePath;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;

import org.junit.Test;

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

public class ThriftPythonEnhancerTest {

  private static final BuildTarget TARGET = BuildTargetFactory.newInstance("//:test#python");
  private static final FakeBuckConfig BUCK_CONFIG = new FakeBuckConfig();
  private static final ThriftBuckConfig THRIFT_BUCK_CONFIG = new ThriftBuckConfig(BUCK_CONFIG);
  private static final ThriftPythonEnhancer ENHANCER = new ThriftPythonEnhancer(
      THRIFT_BUCK_CONFIG,
      ThriftPythonEnhancer.Type.NORMAL);
  private static final ThriftPythonEnhancer TWISTED_ENHANCER = new ThriftPythonEnhancer(
      THRIFT_BUCK_CONFIG,
      ThriftPythonEnhancer.Type.TWISTED);

  private static FakeBuildRule createFakeBuildRule(
      String target,
      SourcePathResolver resolver,
      BuildRule... deps) {
    return new FakeBuildRule(
        new FakeBuildRuleParamsBuilder(BuildTargetFactory.newInstance(target))
            .setDeps(ImmutableSortedSet.copyOf(deps))
            .build(),
        resolver);
  }

  private static ThriftCompiler createFakeThriftCompiler(
      String target,
      SourcePathResolver resolver) {
    return new ThriftCompiler(
        BuildRuleParamsFactory.createTrivialBuildRuleParams(
            BuildTargetFactory.newInstance(target)),
        resolver,
        new TestSourcePath("compiler"),
        ImmutableList.<String>of(),
        Paths.get("output"),
        new TestSourcePath("source"),
        "language",
        ImmutableSet.<String>of(),
        ImmutableList.<Path>of(),
        ImmutableMap.<Path, SourcePath>of());
  }

  @Test
  public void getLanguage() {
    assertEquals(
        "py",
        ENHANCER.getLanguage());
  }

  @Test
  public void getFlavor() {
    assertEquals(
        ImmutableFlavor.of("py"),
        ENHANCER.getFlavor());
  }

  private ImmutableSet<String> addTwisted(ImmutableSet<String> options) {
    return ImmutableSet.<String>builder()
        .add("twisted")
        .addAll(options)
        .build();
  }

  @Test
  public void getOptions() {
    ThriftConstructorArg arg = new ThriftConstructorArg();
    ImmutableSet<String> options;

    // Test empty options.
    options = ImmutableSet.of();
    arg.pyOptions = Optional.of(options);
    assertEquals(
        options,
        ENHANCER.getOptions(TARGET, arg));
    assertEquals(
        addTwisted(options),
        TWISTED_ENHANCER.getOptions(TARGET, arg));

    // Test set options.
    options = ImmutableSet.of("test", "option");
    arg.pyOptions = Optional.of(options);
    assertEquals(
        options,
        ENHANCER.getOptions(TARGET, arg));
    assertEquals(
        addTwisted(options),
        TWISTED_ENHANCER.getOptions(TARGET, arg));

    // Test absent options.
    arg.pyOptions = Optional.absent();
    assertEquals(
        ImmutableSet.<String>of(),
        ENHANCER.getOptions(TARGET, arg));
    assertEquals(
        addTwisted(ImmutableSet.<String>of()),
        TWISTED_ENHANCER.getOptions(TARGET, arg));
  }

  private void expectImplicitDeps(
      ThriftPythonEnhancer enhancer,
      ImmutableSet<String> options,
      ImmutableSet<BuildTarget> expected) {

    ThriftConstructorArg arg = new ThriftConstructorArg();
    arg.pyOptions = Optional.of(options);

    assertEquals(
        expected,
        enhancer.getImplicitDepsForTargetFromConstructorArg(TARGET, arg));
  }

  @Test
  public void getImplicitDeps() {
    // Setup enhancers which set all appropriate values in the config.
    ImmutableMap<String, BuildTarget> config = ImmutableMap.of(
        "python_library", BuildTargetFactory.newInstance("//:python_library"),
        "python_twisted_library", BuildTargetFactory.newInstance("//:python_twisted_library"));
    ImmutableMap.Builder<String, String> strConfig = ImmutableMap.builder();
    for (ImmutableMap.Entry<String, BuildTarget> ent : config.entrySet()) {
      strConfig.put(ent.getKey(), ent.getValue().toString());
    }
    FakeBuckConfig buckConfig = new FakeBuckConfig(
        ImmutableMap.<String, Map<String, String>>of("thrift", strConfig.build()));
    ThriftBuckConfig thriftBuckConfig = new ThriftBuckConfig(buckConfig);
    ThriftPythonEnhancer enhancer = new ThriftPythonEnhancer(
        thriftBuckConfig,
        ThriftPythonEnhancer.Type.NORMAL);
    ThriftPythonEnhancer twistedEnhancer = new ThriftPythonEnhancer(
        thriftBuckConfig,
        ThriftPythonEnhancer.Type.TWISTED);

    // With no options we just need to find the python thrift library.
    expectImplicitDeps(
        enhancer,
        ImmutableSet.<String>of(),
        ImmutableSet.of(
            config.get("python_library")));

    // With the twisted enhancer option we also expect the twisted library.
    expectImplicitDeps(
        twistedEnhancer,
        ImmutableSet.of("twisted"),
        ImmutableSet.of(
            config.get("python_library"),
            config.get("python_twisted_library")));
  }

  @Test
  public void createBuildRule() {
    BuildRuleResolver resolver = new BuildRuleResolver();
    SourcePathResolver pathResolver = new SourcePathResolver(resolver);
    BuildRuleParams flavoredParams =
        BuildRuleParamsFactory.createTrivialBuildRuleParams(TARGET);

    // Add a dummy dependency to the constructor arg to make sure it gets through.
    ThriftConstructorArg arg = new ThriftConstructorArg();
    arg.pyOptions = Optional.absent();
    arg.pyBaseModule = Optional.absent();

    // Setup up some thrift inputs to pass to the createBuildRule method.
    ImmutableMap<String, ThriftSource> sources = ImmutableMap.of(
        "test1.thrift", new ThriftSource(
            createFakeThriftCompiler("//:thrift_source1", pathResolver),
            ImmutableList.<String>of(),
            Paths.get("output1")),
        "test2.thrift", new ThriftSource(
            createFakeThriftCompiler("//:thrift_source2", pathResolver),
            ImmutableList.<String>of(),
            Paths.get("output2")));

    // Create a dummy implicit dep to pass in.
    ImmutableSortedSet<BuildRule> deps = ImmutableSortedSet.<BuildRule>of(
        createFakeBuildRule("//:dep", pathResolver));

    // Run the enhancer to create the language specific build rule.
    PythonLibrary library = ENHANCER.createBuildRule(
        flavoredParams,
        resolver,
        arg,
        sources,
        deps);

    // Verify that the top-level default python lib has correct deps.
    assertEquals(deps, library.getDeps());
  }

  @Test
  public void baseModule() {
    BuildTarget target = BuildTargetFactory.newInstance("//test:test");
    BuildRuleResolver resolver = new BuildRuleResolver();
    SourcePathResolver pathResolver = new SourcePathResolver(resolver);
    BuildRuleParams flavoredParams =
        BuildRuleParamsFactory.createTrivialBuildRuleParams(target);

    // Add a dummy dependency to the constructor arg to make sure it gets through.
    ThriftConstructorArg arg = new ThriftConstructorArg();
    arg.pyOptions = Optional.absent();

    // Setup up some thrift inputs to pass to the createBuildRule method.
    ImmutableMap<String, ThriftSource> sources = ImmutableMap.of(
        "test.thrift", new ThriftSource(
            createFakeThriftCompiler("//:thrift_source", pathResolver),
            ImmutableList.<String>of(),
            Paths.get("output")));

    // Verify that not setting the base module parameter defaults to the build target base path.
    arg.pyBaseModule = Optional.absent();
    PythonLibrary normal = ENHANCER.createBuildRule(
        flavoredParams,
        resolver,
        arg,
        sources,
        ImmutableSortedSet.<BuildRule>of());
    for (ImmutableMap.Entry<Path, SourcePath> ent : normal.getSrcs().entrySet()) {
      assertTrue(ent.getKey().toString(), ent.getKey().startsWith(target.getBasePath()));
    }

    // Verify that setting the base module uses it correctly.
    arg.pyBaseModule = Optional.of("blah");
    PythonLibrary baseModule = ENHANCER.createBuildRule(
        flavoredParams,
        resolver,
        arg,
        sources,
        ImmutableSortedSet.<BuildRule>of());
    for (ImmutableMap.Entry<Path, SourcePath> ent : baseModule.getSrcs().entrySet()) {
      assertTrue(ent.getKey().startsWith(Paths.get(arg.pyBaseModule.get())));
    }
  }

}
