/*
 * Copyright 2012-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.parser;

import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.FlavorParser;
import com.facebook.buck.model.ImmutableBuildTarget;
import com.facebook.buck.model.ImmutableFlavor;
import com.facebook.buck.model.ImmutableUnflavoredBuildTarget;
import com.facebook.buck.model.UnflavoredBuildTarget;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;

import java.util.HashSet;
import java.util.List;

public class BuildTargetParser {

  private static final String BUILD_RULE_PREFIX = "//";
  private static final String BUILD_RULE_SEPARATOR = ":";
  private static final String REPOSITORY_STARTER = "@";
  private static final Splitter BUILD_RULE_SEPARATOR_SPLITTER = Splitter.on(BUILD_RULE_SEPARATOR);
  private static final List<String> INVALID_BUILD_RULE_SUBSTRINGS = ImmutableList.of("..", "./");

  private final ImmutableMap<Optional<String>, Optional<String>> localToCanonicalRepoNamesMap;
  private final FlavorParser flavorParser = new FlavorParser();

  public BuildTargetParser() {
    // By default, use a canonical names map that only allows targets with no repo name.
    this(ImmutableMap.of(Optional.<String>absent(), Optional.<String>absent()));
  }

  /**
   *
   * @param localToCanonicalRepoNamesMap
   *          Internally, buck uses a unique, global name to refer to each repository.  All targets
   *          that live in repo X are represented internally using this unique name. However, other
   *          repos might have their own names for X, and rules inside of X will refer to each other
   *          with no explicit repo at all. This map provides the translation from local repo names
   *          used within the current repo to their unique, global repo names.
   */
  public BuildTargetParser(
      ImmutableMap<Optional<String>, Optional<String>> localToCanonicalRepoNamesMap) {
    this.localToCanonicalRepoNamesMap = localToCanonicalRepoNamesMap;
  }

  /**
   * @param buildTargetName either a fully-qualified name or relative to the {@link BuildTargetPatternParser}.
   *     For example, inside {@code first-party/orca/orcaapp/BUILD}, which can be obtained by
   *     calling {@code ParseContext.forBaseName("first-party/orca/orcaapp")},
   *     {@code //first-party/orca/orcaapp:assets} and {@code :assets} refer to the same target.
   *     However, from the command line the context is obtained by calling
   *     {@link BuildTargetPatternParser#fullyQualified(BuildTargetParser)} and relative names are
   *     not recognized.
   * @param buildTargetPatternParser how targets should be interpreted, such in the context of a
   *     specific build file or only as fully-qualified names (as is the case for targets from the
   *     command line).
   */
  public BuildTarget parse(
      String buildTargetName,
      BuildTargetPatternParser buildTargetPatternParser) {

    for (String invalidSubstring : INVALID_BUILD_RULE_SUBSTRINGS) {
      if (buildTargetName.contains(invalidSubstring)) {
        throw new BuildTargetParseException(
            String.format("%s cannot contain %s", buildTargetName, invalidSubstring));
      }
    }

    if (buildTargetName.endsWith(BUILD_RULE_SEPARATOR) &&
        !buildTargetPatternParser.isWildCardAllowed()) {
      throw new BuildTargetParseException(
          String.format("%s cannot end with a colon", buildTargetName));
    }

    Optional<String> givenRepoName = Optional.absent();
    String targetAfterRepo = buildTargetName;
    if (buildTargetName.startsWith(REPOSITORY_STARTER)) {
      if (!buildTargetName.contains(BUILD_RULE_PREFIX)) {
        throw new BuildTargetParseException(
            String.format(
                "Cross-repo paths must contain %s (found %s)",
                BUILD_RULE_PREFIX,
                buildTargetName));
      }
      int slashIndex = buildTargetName.indexOf(BUILD_RULE_PREFIX);
      givenRepoName = Optional.of(
          buildTargetName.substring(REPOSITORY_STARTER.length(), slashIndex));
      targetAfterRepo = buildTargetName.substring(slashIndex);
    }

    if (givenRepoName.isPresent() && givenRepoName.get().isEmpty()) {
      throw new BuildTargetParseException("Repo name must not be empty.");
    }

    if (!localToCanonicalRepoNamesMap.containsKey(givenRepoName)) {
      throw new HumanReadableException(String.format(
          "In build target '%s', repo '%s' is not defined.",
          buildTargetName,
          givenRepoName));
    }

    List<String> parts = BUILD_RULE_SEPARATOR_SPLITTER.splitToList(targetAfterRepo);
    if (parts.size() != 2) {
      throw new BuildTargetParseException(String.format(
          "%s must contain exactly one colon (found %d)", buildTargetName, parts.size() - 1));
    }

    String baseName =
        parts.get(0).isEmpty() ? buildTargetPatternParser.getBaseName() : parts.get(0);
    String shortName = parts.get(1);
    Iterable<String> flavorNames = new HashSet<>();
    int hashIndex = shortName.indexOf("#");
    if (hashIndex != -1 && hashIndex < shortName.length()) {
      flavorNames = flavorParser.parseFlavorString(shortName.substring(hashIndex + 1));
      shortName = shortName.substring(0, hashIndex);
    }

    Preconditions.checkNotNull(baseName);
    // On Windows, baseName may contain backslashes, which are not permitted by BuildTarget.
    baseName = baseName.replace("\\", "/");
    String fullyQualifiedName = baseName + ':' + shortName;
    if (!fullyQualifiedName.startsWith(BUILD_RULE_PREFIX)) {
      throw new BuildTargetParseException(
          String.format("%s must start with %s", fullyQualifiedName, BUILD_RULE_PREFIX));
    }

    ImmutableUnflavoredBuildTarget.Builder unflavoredBuilder =
        UnflavoredBuildTarget.builder(baseName, shortName);
    Optional<String> canonicalRepoName = Preconditions.checkNotNull(
        localToCanonicalRepoNamesMap.get(givenRepoName));
    if (canonicalRepoName.isPresent()) {
      unflavoredBuilder.setRepository(canonicalRepoName.get());
    }
    ImmutableBuildTarget.Builder builder = BuildTarget.builder(unflavoredBuilder.build());
    for (String flavor : flavorNames) {
      builder.addFlavors(ImmutableFlavor.of(flavor));
    }
    return builder.build();
  }
}
