// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.lib.syntax;

import com.google.common.base.Preconditions;
import com.google.devtools.build.lib.events.Location;
import java.io.IOException;
import java.util.List;
import javax.annotation.Nullable;

/**
 * Syntax node for a function argument.
 *
 * <p>Argument is a base class for arguments passed in a call (@see Argument.Passed)
 * or defined as part of a function definition (@see Parameter).
 * It is notably used by some {@link Parser} and printer functions.
 */
public abstract class Argument extends ASTNode {

  public boolean isStar() {
    return false;
  }

  public boolean isStarStar() {
    return false;
  }

  /**
   * Argument.Passed is the class of arguments passed in a function call
   * (as opposed to being used in a definition -- @see Parameter for that).
   * Argument.Passed is usually what we mean when informally say "argument".
   *
   * <p>An Argument.Passed can be Positional, Keyword, Star, or StarStar.
   */
  public abstract static class Passed extends Argument {
    /** the value to be passed by this argument */
    protected final Expression value;

    private Passed(Expression value) {
      this.value = Preconditions.checkNotNull(value);
    }

    public boolean isPositional() {
      return false;
    }

    public boolean isKeyword() {
      return false;
    }

    /** @deprecated Prefer {@link #getIdentifier()} instead. */
    @Deprecated
    @Nullable
    public String getName() { // only for keyword arguments
      return null;
    }

    @Nullable
    public Identifier getIdentifier() {
      return null;
    }

    public Expression getValue() {
      return value;
    }

    @Override
    public void accept(SyntaxTreeVisitor visitor) {
      visitor.visit(this);
    }
  }

  /** positional argument: Expression */
  public static final class Positional extends Passed {

    Positional(Expression value) {
      super(value);
    }

    @Override
    public boolean isPositional() {
      return true;
    }

    @Override
    public void prettyPrint(Appendable buffer) throws IOException {
      value.prettyPrint(buffer);
    }
  }

  /** keyword argument: K = Expression */
  public static final class Keyword extends Passed {

    final Identifier identifier;

    Keyword(Identifier identifier, Expression value) {
      super(value);
      this.identifier = identifier;
    }

    @Override
    public String getName() {
      return identifier.getName();
    }

    @Override
    public Identifier getIdentifier() {
      return identifier;
    }

    @Override
    public boolean isKeyword() {
      return true;
    }

    @Override
    public void prettyPrint(Appendable buffer) throws IOException {
      buffer.append(identifier.getName());
      buffer.append(" = ");
      value.prettyPrint(buffer);
    }
  }

  /** positional rest (starred) argument: *Expression */
  public static final class Star extends Passed {

    Star(Expression value) {
      super(value);
    }

    @Override
    public boolean isStar() {
      return true;
    }

    @Override
    public void prettyPrint(Appendable buffer) throws IOException {
      buffer.append('*');
      value.prettyPrint(buffer);
    }
  }

  /** keyword rest (star_starred) parameter: **Expression */
  public static final class StarStar extends Passed {

    StarStar(Expression value) {
      super(value);
    }

    @Override
    public boolean isStarStar() {
      return true;
    }

    @Override
    public void prettyPrint(Appendable buffer) throws IOException {
      buffer.append("**");
      value.prettyPrint(buffer);
    }
  }

  /** Some arguments failed to satisfy python call convention strictures */
  static class ArgumentException extends Exception {
    Location location;

    /** construct an ArgumentException from a message only */
    ArgumentException(Location location, String message) {
      super(message);
      this.location = location;
    }

    Location getLocation() {
      return location;
    }
  }

  /**
   * Validate that the list of Argument's, whether gathered by the Parser or from annotations,
   * satisfies the requirements: first Positional arguments, then Keyword arguments, then an
   * optional *arg argument, finally an optional **kwarg argument.
   */
  public static void validateFuncallArguments(List<Passed> arguments) throws ArgumentException {
    int i = 0;
    int len = arguments.size();

    while (i < len && arguments.get(i).isPositional()) {
      i++;
    }

    while (i < len && arguments.get(i).isKeyword()) {
      i++;
    }

    if (i < len && arguments.get(i).isStar()) {
      i++;
    }

    if (i < len && arguments.get(i).isStarStar()) {
      i++;
    }

    // If there's no argument left, everything is correct.
    if (i == len) {
      return;
    }

    Location loc = arguments.get(i).getLocation();
    if (arguments.get(i).isPositional()) {
      throw new ArgumentException(
          loc, "positional argument is misplaced (positional arguments come first)");
    }

    if (arguments.get(i).isKeyword()) {
      throw new ArgumentException(
          loc,
          "keyword argument is misplaced (keyword arguments must be before any *arg or **kwarg)");
    }

    if (i < len && arguments.get(i).isStar()) {
      throw new ArgumentException(loc, "*arg argument is misplaced");
    }

    if (i < len && arguments.get(i).isStarStar()) {
      throw new ArgumentException(loc, "**kwarg argument is misplaced (there can be only one)");
    }
  }

  @Override
  public final void prettyPrint(Appendable buffer, int indentLevel) throws IOException {
    prettyPrint(buffer);
  }

  @Override
  public abstract void prettyPrint(Appendable buffer) throws IOException;
}
