/*
 * Copyright 2016 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.idea.blaze.base.lang.buildfile.psi;

import com.google.idea.blaze.base.lang.buildfile.psi.util.PsiUtils;
import com.google.idea.blaze.base.lang.buildfile.references.FuncallReference;
import com.google.idea.blaze.base.lang.buildfile.references.LabelUtils;
import com.google.idea.blaze.base.model.primitives.Label;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import icons.BlazeIcons;
import javax.annotation.Nullable;
import javax.swing.Icon;

/**
 * PSI element for an function call.<br>
 * Could be a top-level rule, Skylark function reference, or general some other python function call
 */
public class FuncallExpression extends BuildElementImpl
    implements Expression, PsiNameIdentifierOwner {

  public FuncallExpression(ASTNode astNode) {
    super(astNode);
  }

  @Override
  protected void acceptVisitor(BuildElementVisitor visitor) {
    visitor.visitFuncallExpression(this);
  }

  /** The name of the function being called. */
  @Nullable
  public String getFunctionName() {
    ASTNode node = getFunctionNameNode();
    return node != null ? node.getText() : null;
  }

  @Override
  @Nullable
  public String getName() {
    return getNameArgumentValue();
  }

  @Nullable
  @Override
  public PsiElement getNameIdentifier() {
    Argument.Keyword name = getNameArgument();
    return name != null ? name.getValue() : null;
  }

  @Override
  public PsiElement setName(String name) throws IncorrectOperationException {
    StringLiteral nameNode = getNameArgumentValueNode();
    if (nameNode == null) {
      return this;
    }
    ASTNode newChild = PsiUtils.createNewLabel(getProject(), name);
    nameNode.getNode().replaceChild(nameNode.getNode().getFirstChildNode(), newChild);
    return this;
  }

  /** The function name */
  @Nullable
  public ASTNode getFunctionNameNode() {
    PsiElement argList = getArgList();
    if (argList != null) {
      // We want the reference expr directly prior to the open parenthesis.
      // This accounts for Skylark native.rule calls.
      PsiElement prev = argList.getPrevSibling();
      if (prev instanceof ReferenceExpression) {
        return prev.getNode();
      }
    }
    return getNode().findChildByType(BuildElementTypes.REFERENCE_EXPRESSION);
  }

  /** Top-level funcalls are almost always BUILD rules. */
  public boolean isTopLevel() {
    ASTNode parent = getNode().getTreeParent();
    return parent == null || parent.getElementType() == BuildElementTypes.BUILD_FILE;
  }

  public boolean mightBeBuildRule() {
    return isTopLevel() || getNameArgument() != null;
  }

  @Nullable
  public Label resolveBuildLabel() {
    BuildFile containingFile = getContainingFile();
    if (containingFile == null
        || containingFile.getBlazeFileType() == BuildFile.BlazeFileType.SkylarkExtension) {
      return null;
    }
    return LabelUtils.createLabelFromRuleName(getBlazePackage(), getNameArgumentValue());
  }

  @Nullable
  public ArgumentList getArgList() {
    return findChildByType(BuildElementTypes.ARGUMENT_LIST);
  }

  public Argument[] getArguments() {
    ArgumentList argList = getArgList();
    return argList != null ? argList.getArguments() : Argument.EMPTY_ARRAY;
  }

  /** Keyword argument with name "name", if one is present. */
  @Nullable
  public Argument.Keyword getNameArgument() {
    return getKeywordArgument("name");
  }

  @Nullable
  public Argument.Keyword getKeywordArgument(String name) {
    ArgumentList argList = getArgList();
    return argList != null ? argList.getKeywordArgument(name) : null;
  }

  /** StringLiteral value of keyword argument with name "name", if one is present. */
  @Nullable
  public StringLiteral getNameArgumentValueNode() {
    Argument.Keyword name = getNameArgument();
    Expression expr = name != null ? name.getValue() : null;
    if (expr instanceof StringLiteral) {
      return ((StringLiteral) expr);
    }
    return null;
  }

  /** Value of keyword argument with name "name", if one is present. */
  @Nullable
  public String getNameArgumentValue() {
    StringLiteral node = getNameArgumentValueNode();
    return node != null ? node.getStringContents() : null;
  }

  @Override
  public Icon getIcon(int flags) {
    return mightBeBuildRule() ? BlazeIcons.BuildRule : null;
  }

  @Override
  public String getPresentableText() {
    String name = getFunctionName();
    if (name == null) {
      return super.getPresentableText();
    }
    String targetName = getNameArgumentValue();
    return targetName != null ? name + "(\"" + targetName + "\")" : name;
  }

  @Override
  @Nullable
  public FuncallReference getReference() {
    ASTNode nameNode = getFunctionNameNode();
    if (nameNode == null) {
      return null;
    }
    TextRange range = PsiUtils.childRangeInParent(getTextRange(), nameNode.getTextRange());
    return new FuncallReference(this, range);
  }

  /**
   * Searches all StringLiteral children of this element, for one which references the desired
   * target expression.
   */
  @Nullable
  public StringLiteral findChildReferenceToTarget(final FuncallExpression targetRule) {
    final StringLiteral[] child = new StringLiteral[1];
    Processor<StringLiteral> processor =
        stringLiteral -> {
          PsiElement ref = stringLiteral.getReferencedElement();
          if (targetRule.equals(ref)) {
            child[0] = stringLiteral;
            return false;
          }
          return true;
        };
    PsiUtils.processChildrenOfType(this, processor, StringLiteral.class);
    return child[0];
  }
}
