/*
 * Copyright 2000-2012 JetBrains s.r.o.
 *
 * 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.intellij.psi.impl.source.tree.java;

import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyadicExpression;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.CompositeElement;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.tree.IElementType;

public class ReplaceExpressionUtil {
  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.ReplaceExpressionUtil");

  public static boolean isNeedParenthesis(ASTNode oldExpr, ASTNode newExpr) {
    final ASTNode oldParent = oldExpr.getTreeParent();
    if (!ElementType.EXPRESSION_BIT_SET.contains(oldParent.getElementType())) return false;
    int priority = getExpressionPriority(newExpr);
    int parentPriority = getExpressionPriority(oldParent);
    if (priority > parentPriority) return false;
    IElementType i = oldParent.getElementType();
    if (i == JavaElementType.ASSIGNMENT_EXPRESSION) {
      return priority < parentPriority || ((CompositeElement)oldParent).getChildRole(oldExpr) == ChildRole.LOPERAND;
    }
    else if (i == JavaElementType.CONDITIONAL_EXPRESSION) {
      int role = ((CompositeElement)oldParent).getChildRole(oldExpr);
      if (role == ChildRole.THEN_EXPRESSION) return false;
      return priority < parentPriority || role != ChildRole.ELSE_EXPRESSION;
    }
    else if (i == JavaElementType.BINARY_EXPRESSION || i == JavaElementType.POLYADIC_EXPRESSION) {
      if (priority < parentPriority) return true;
      PsiElement element = SourceTreeToPsiMap.treeElementToPsi(oldParent);
      IElementType opType = ((PsiPolyadicExpression)element).getOperationTokenType();
      return ((CompositeElement)oldParent).getChildRole(oldExpr) != ChildRole.LOPERAND &&
             opType != JavaTokenType.PLUS &&
             opType != JavaTokenType.ASTERISK &&
             opType != JavaTokenType.ANDAND &&
             opType != JavaTokenType.OROR;
    }
    else if (i == JavaElementType.INSTANCE_OF_EXPRESSION) {
      return priority < parentPriority;
    }
    else if (i == JavaElementType.PREFIX_EXPRESSION || i == JavaElementType.TYPE_CAST_EXPRESSION) {
      return priority < parentPriority;
    }
    else if (i == JavaElementType.POSTFIX_EXPRESSION) {
      return priority <= parentPriority;
    }
    else if (i == JavaElementType.REFERENCE_EXPRESSION) {
      return priority < parentPriority;
    }
    else if (i == JavaElementType.METHOD_CALL_EXPRESSION) {
      return false;
    }
    else if (i == JavaElementType.NEW_EXPRESSION) {
      return false;
    }
    else if (i == JavaElementType.ARRAY_ACCESS_EXPRESSION) {
      int role = ((CompositeElement)oldParent).getChildRole(oldExpr);
      return role != ChildRole.ARRAY_DIMENSION && priority < parentPriority;
    }
    else if (i == JavaElementType.ARRAY_INITIALIZER_EXPRESSION) {
      return false;
    }
    else if (i == JavaElementType.PARENTH_EXPRESSION) {
      return false;
    }
    else if (i == JavaElementType.LITERAL_EXPRESSION ||
             i == JavaElementType.THIS_EXPRESSION ||
             i == JavaElementType.SUPER_EXPRESSION ||
             i == JavaElementType.CLASS_OBJECT_ACCESS_EXPRESSION ||
             i == JavaElementType.LAMBDA_EXPRESSION ||
             i == JavaElementType.METHOD_REF_EXPRESSION ) {
      return false;
    }

    LOG.assertTrue(false);
    return false;
  }

  private static int getExpressionPriority(ASTNode expr) {
    IElementType i = expr.getElementType();
    if (i == JavaElementType.ASSIGNMENT_EXPRESSION) {
      return 0;
    }
    else if (i == JavaElementType.CONDITIONAL_EXPRESSION) {
      return 1;
    }
    else if (i == JavaElementType.BINARY_EXPRESSION || i == JavaElementType.POLYADIC_EXPRESSION) {
      PsiElement element = SourceTreeToPsiMap.treeElementToPsi(expr);
      IElementType opType = ((PsiPolyadicExpression)element).getOperationTokenType();
      if (opType == JavaTokenType.OROR) {
        return 2;
      }
      else if (opType == JavaTokenType.ANDAND) {
        return 3;
      }
      else if (opType == JavaTokenType.OR) {
        return 4;
      }
      else if (opType == JavaTokenType.XOR) {
        return 5;
      }
      else if (opType == JavaTokenType.AND) {
        return 6;
      }
      else if (opType == JavaTokenType.EQEQ || opType == JavaTokenType.NE) {
        return 7;
      }
      else if (opType == JavaTokenType.LT || opType == JavaTokenType.GT || opType == JavaTokenType.LE || opType == JavaTokenType.GE) {
        return 8;
      }
      else if (opType == JavaTokenType.LTLT || opType == JavaTokenType.GTGT || opType == JavaTokenType.GTGTGT) {
        return 9;
      }
      else if (opType == JavaTokenType.PLUS || opType == JavaTokenType.MINUS) {
        return 10;
      }
      else if (opType == JavaTokenType.ASTERISK || opType == JavaTokenType.DIV || opType == JavaTokenType.PERC) {
        return 11;
      }
      return 8;
    }
    else if (i == JavaElementType.INSTANCE_OF_EXPRESSION) {
      return 8;
    }
    else if (i == JavaElementType.PREFIX_EXPRESSION || i == JavaElementType.TYPE_CAST_EXPRESSION) {
      return 12;
    }
    else if (i == JavaElementType.POSTFIX_EXPRESSION) {
      return 13;
    }
    else if (i == JavaElementType.LITERAL_EXPRESSION ||
             i == JavaElementType.REFERENCE_EXPRESSION ||
             i == JavaElementType.THIS_EXPRESSION ||
             i == JavaElementType.SUPER_EXPRESSION ||
             i == JavaElementType.PARENTH_EXPRESSION ||
             i == JavaElementType.METHOD_CALL_EXPRESSION ||
             i == JavaElementType.CLASS_OBJECT_ACCESS_EXPRESSION ||
             i == JavaElementType.NEW_EXPRESSION ||
             i == JavaElementType.ARRAY_ACCESS_EXPRESSION ||
             i == JavaElementType.ARRAY_INITIALIZER_EXPRESSION ||
             i == JavaElementType.JAVA_CODE_REFERENCE ||
             i == JavaElementType.METHOD_REF_EXPRESSION ||
             i == JavaElementType.LAMBDA_EXPRESSION ||
             i == JavaElementType.EMPTY_EXPRESSION) {
      return 14;
    }
    else {
      LOG.error("Unknown element type:" + i);
      return -1;
    }
  }
}
