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

import com.facebook.buck.cxx.CxxPlatform;
import com.facebook.buck.io.MorePaths;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.graph.AbstractBreadthFirstTraversal;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.coercer.Either;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;

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

public class PythonUtil {

  private PythonUtil() {}

  public static ImmutableMap<Path, SourcePath> toModuleMap(
      BuildTarget target,
      SourcePathResolver resolver,
      String parameter,
      Path baseModule,
      Optional<Either<ImmutableSortedSet<SourcePath>, ImmutableMap<String, SourcePath>>> inputs) {

    if (!inputs.isPresent()) {
      return ImmutableMap.of();
    }

    final ImmutableMap<String, SourcePath> namesAndSourcePaths;

    if (inputs.get().isLeft()) {
      namesAndSourcePaths = resolver.getSourcePathNames(
          target,
          parameter,
          inputs.get().getLeft());
    } else {
      namesAndSourcePaths = inputs.get().getRight();
    }

    ImmutableMap.Builder<Path, SourcePath> moduleNamesAndSourcePaths = ImmutableMap.builder();

    for (ImmutableMap.Entry<String, SourcePath> entry : namesAndSourcePaths.entrySet()) {
      moduleNamesAndSourcePaths.put(
          baseModule.resolve(entry.getKey()),
          entry.getValue());
    }
    return moduleNamesAndSourcePaths.build();
  }

  /** Convert a path to a module to it's module name as referenced in import statements. */
  public static String toModuleName(BuildTarget target, String name) {
    int ext = name.lastIndexOf('.');
    if (ext == -1) {
      throw new HumanReadableException(
          "%s: missing extension for module path: %s",
          target,
          name);
    }
    name = name.substring(0, ext);
    return MorePaths.pathWithUnixSeparators(name).replace('/', '.');
  }

  public static ImmutableSortedSet<BuildRule> getDepsFromComponents(
      SourcePathResolver resolver,
      PythonPackageComponents components) {
    return ImmutableSortedSet.<BuildRule>naturalOrder()
        .addAll(resolver.filterBuildRuleInputs(components.getModules().values()))
        .addAll(resolver.filterBuildRuleInputs(components.getResources().values()))
        .addAll(resolver.filterBuildRuleInputs(components.getNativeLibraries().values()))
        .build();
  }

  public static PythonPackageComponents getAllComponents(
      BuildRuleParams params,
      PythonPackageComponents packageComponents,
      final CxxPlatform cxxPlatform) {

    final PythonPackageComponents.Builder components =
        new PythonPackageComponents.Builder(params.getBuildTarget());

    // Add components from our self.
    components.addComponent(packageComponents, params.getBuildTarget());

    // Walk all our transitive deps to build our complete package that we'll
    // turn into an executable.
    new AbstractBreadthFirstTraversal<BuildRule>(params.getDeps()) {
      @Override
      public ImmutableSortedSet<BuildRule> visit(BuildRule rule) {
        // We only process and recurse on instances of PythonPackagable.
        if (rule instanceof PythonPackagable) {
          PythonPackagable lib = (PythonPackagable) rule;

          // Add all components from the python packable into our top-level
          // package.
          components.addComponent(
              lib.getPythonPackageComponents(cxxPlatform),
              rule.getBuildTarget());

          // Return all our deps to recurse on them.
          return rule.getDeps();
        }

        // Don't recurse on anything from other rules.
        return ImmutableSortedSet.of();
      }
    }.start();

    return components.build();
  }

  public static Path getBasePath(BuildTarget target, Optional<String> override) {
    return override.isPresent()
        ? Paths.get(override.get().replace('.', '/'))
        : target.getBasePath();
  }

}
