/*
 * Copyright 2013-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.cli;

import com.facebook.buck.util.HumanReadableException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class abstracts the data for a dependency query that the "buck query" command processes.
 * All queries reference a target. Queries that reference a source are queries for paths from
 * target back to source, and queries that don't reference a source are queries for all
 * dependencies of a target.
 */
public class DependencyQuery {

  /**
   * The ARROW_PATTERN is used for extracting the three components of a Buck query.
   * These are the target rule, the (optional) source rule, and the depth specifier inside
   * the dependency arrow. Target -depth> Source.
   * <p>
   * The target rule is mandatory so we use S+, while source rule is optional so it is specified
   * by S*. A nonexistent source rule will still be captured as an empty string in the third group
   * of the regex. Spaces are required between the build rules and the arrow, though a query
   * can also end immediately after the arrow. Inside the -?> arrow, users can specify either
   * a numeric depth \\d*, a single '*', or nothing (which is taken care of by the \\d* regex).
   */
  @VisibleForTesting
  static final Pattern ARROW_PATTERN = Pattern.compile(
      "\\s*(\\S+)\\s+"
    + "-(\\d*|\\*)>"
    + "(?:\\s+|$)(\\S*)\\s*");

  // TODO: Convert build rules from strings to BuildTargets
  private final String target;
  private final Optional<String> source;
  private final Optional<Integer> depth;

  private DependencyQuery(Optional<Integer> depth, String target) {
    this(depth, target, /* source */ Optional.<String>absent());
  }

  private DependencyQuery(Optional<Integer> depth, String target, Optional<String> source) {
    Preconditions.checkNotNull(depth);
    Preconditions.checkNotNull(target);
    Preconditions.checkNotNull(source);
    this.depth = depth;
    this.target = target;
    this.source = source;
  }

  String getTarget() {
    return target;
  }

  Optional<String> getSource() {
    return source;
  }

  Optional<Integer> getDepth() {
    return depth;
  }

  /**
   * This static factory method parses an input string query.
   * <p>
   * The general structure of a query is T -D> S.
   * T is the target, specified as a fully qualified target name. It is required.
   * S is the source, similarly fully qualified. When it is specified we assume you are
   *     querying for the dependency paths from T to S. When it is omitted we assume you are
   *     querying for all of the dependencies of T.
   * D is the depth. It controls the depth to which we will traverse the dependency graph
   *     starting at T. D=1 means we will search only for immediate dependencies. D=* means the
   *     depth will be unbounded. If D is omitted, as in "T -> S" then it defaults to *.
   * <p>
   * Example Queries:
   *     buck query '//:target -2>' finds all dependencies of dependencies of target
   *     buck query '//:target -*> //:source' finds all dependency paths from target to source
   *
   * @return dependency query we constructed based on string.
   * @throws HumanReadableException on bad query strings.
   */
  static DependencyQuery parseQueryString(String queryString) throws HumanReadableException {
    Matcher queryMatcher = ARROW_PATTERN.matcher(queryString);
    if (!queryMatcher.matches()) {
      throw new HumanReadableException(String.format("Invalid query string: %s.", queryString));
    }

    String arrowType = queryMatcher.group(2).trim();
    Optional<Integer> depth;
    if (arrowType.isEmpty() || arrowType.equals("*")) {
      depth = Optional.absent();
    } else {
      try {
        int numDepth = Integer.parseInt(arrowType);
        if (numDepth < 0) {
          throw new IllegalArgumentException(String.format("Negative depth: %d.", numDepth));
        }
        depth = Optional.of(numDepth);
      } catch (IllegalArgumentException e) {
        throw new HumanReadableException(e, String.format("Invalid search depth: %s.", arrowType));
      }
    }

    String target = queryMatcher.group(1).trim();
    final String fullyQualifiedTarget =
        CommandLineBuildTargetNormalizer.normalizeBuildTargetIdentifier(target);

    String source = queryMatcher.group(3).trim();
    String fullyQualifiedSource =
        CommandLineBuildTargetNormalizer.normalizeBuildTargetIdentifier(source);

    if (source.isEmpty()) {
      return new DependencyQuery(depth, fullyQualifiedTarget);
    } else {
      return new DependencyQuery(depth, fullyQualifiedTarget, Optional.of(fullyQualifiedSource));
    }
  }
}
