/*
 * Copyright 2008 Google 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.google.gwt.dev.jjs.impl;

import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JBooleanLiteral;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JConditional;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JExpressionStatement;
import com.google.gwt.dev.jjs.ast.JIfStatement;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JPrefixOperation;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JUnaryOperation;
import com.google.gwt.dev.jjs.ast.JUnaryOperator;
import com.google.gwt.dev.jjs.ast.JValueLiteral;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;

import java.util.List;

/**
 * Methods that both construct and try to simplify AST nodes. If simplification
 * fails, then the methods will return an original, unmodified version of the
 * node if one is supplied. The routines do not recurse into their arguments;
 * the arguments are assumed to already be simplified as much as possible.
 */
public class Simplifier {
  /**
   * TODO: if the AST were normalized, we wouldn't need this.
   */
  public static boolean isEmpty(JStatement stmt) {
    if (stmt == null) {
      return true;
    }
    return (stmt instanceof JBlock && ((JBlock) stmt).getStatements().isEmpty());
  }

  /**
   * Negate the supplied expression if negating it makes the expression shorter.
   * Otherwise, return null.
   */
  private static JExpression maybeUnflipBoolean(JExpression expr) {
    if (expr instanceof JUnaryOperation) {
      JUnaryOperation unop = (JUnaryOperation) expr;
      if (unop.getOp() == JUnaryOperator.NOT) {
        return unop.getArg();
      }
    }
    return null;
  }

  private static <T> List<T> allButLast(List<T> list) {
    return list.subList(0, list.size() - 1);
  }

  private static <T> T last(List<T> list) {
    return list.get(list.size() - 1);
  }

  /**
   * This class provides only static methods. No instances will ever be created.
   */
  private Simplifier() {
  }

  /**
   * Simplify cast operations. Used when creating a cast in DeadCodeElimination. For simplifying
   * casts that are actually in the AST, cast(JCastOperation) is used instead.
   *
   * <pre>
   * (int) 1 -> 1
   * (A) (a,b) -> (a, (A) b)
   * </pre>
   *
   * @param type the Type to cast the expression <code>exp</code> to.
   * @param exp the current JExpression under the cast as it is being simplified.
   * @return the simplified expression.
   */
  public static JExpression cast(JType type, JExpression exp) {
    return castImpl(null, exp.getSourceInfo(), type, exp);
  }

  /**
   * Simplify cast operations.
   *
   * <pre>
   * (int) 1 -> 1
   * (A) (a,b) -> (a, (A) b)
   * </pre>
   *
   * @param exp a JCastOperation to be simplified.
   * @return the simplified expression if a simplification was possible; <code>exp</code> otherwise.
   */
  public static JExpression cast(JCastOperation exp) {
    return castImpl(exp, exp.getSourceInfo(), exp.getCastType(), exp.getExpr());
  }

  private static JExpression castImpl(JExpression original, SourceInfo info, JType type,
      JExpression exp) {
    info = getBestSourceInfo(original, info, exp);
    if (exp instanceof JMultiExpression) {
      // (T)(a,b,c) -> a,b,(T) c
      JMultiExpression expMulti = (JMultiExpression) exp;
      JMultiExpression newMulti = new JMultiExpression(info);
      newMulti.addExpressions(allButLast(expMulti.getExpressions()));
      newMulti.addExpressions(castImpl(null, info, type, last(expMulti.getExpressions())));
      // TODO(rluble): immediately simplify the resulting multi.
      // TODO(rluble): refactor common outward JMultiExpression movement.
      return newMulti;
    }
    if (type == exp.getType()) {
      return exp;
    }

    if (type.isPrimitiveType() && (exp instanceof JValueLiteral)) {
      // Statically evaluate casting literals.
      JPrimitiveType primitiveType = (JPrimitiveType) type;
      JValueLiteral expLit = (JValueLiteral) exp;
      JValueLiteral casted = primitiveType.coerce(expLit);
      if (casted != null) {
        return casted;
      }
    }

    /*
     * Discard casts from byte or short to int, because such casts are always
     * implicit anyway. Cannot coerce char since that would change the semantics
     * of concat.
     */
    if (type == JPrimitiveType.INT) {
      JType expType = exp.getType();
      if ((expType == JPrimitiveType.SHORT)
          || (expType == JPrimitiveType.BYTE)) {
        return exp;
      }
    }

    // no simplification made
    if (original != null) {
      return original;
    }
    return new JCastOperation(info, type, exp);
  }

  /**
   * Simplify conditional expressions.
   *
   * <pre>
   * (a,b,c)?d:e -> a,b,(c?d:e)
   * true ? then : else -> then
   * false ? then : else -> else
   * cond ? true : else) -> cond || else
   * cond ? false : else -> !cond && else
   * cond ? then : true -> !cond || then
   * cond ? then : false -> cond && then
   * !cond ? then : else -> cond ? else : then
   * </pre>
   *
   * @param exp a JCondintional to be simplified.
   * @return the simplified expression if a simplification was possible; <code>exp</code> otherwise.
   */
  public static JExpression conditional(JConditional exp) {
    return conditionalImpl(exp, exp.getSourceInfo(), exp.getType(), exp.getIfTest(),
        exp.getThenExpr(), exp.getElseExpr());
  }

  private static JExpression conditionalImpl(JConditional original, SourceInfo info, JType type,
      JExpression condExpr, JExpression thenExpr, JExpression elseExpr) {
    info = getBestSourceInfo(original, info, condExpr);
    if (condExpr instanceof JMultiExpression) {
      // (a,b,c)?d:e -> a,b,(c?d:e)
      // TODO(spoon): do this outward multi movement for all AST nodes
      JMultiExpression condMulti = (JMultiExpression) condExpr;
      JMultiExpression newMulti = new JMultiExpression(info);
      newMulti.addExpressions(allButLast(condMulti.getExpressions()));
      newMulti.addExpressions(conditionalImpl(null, info, type, last(condMulti.getExpressions()),
          thenExpr, elseExpr));
      // TODO(spoon): immediately simplify the resulting multi
      return newMulti;
    }
    if (condExpr instanceof JBooleanLiteral) {
      if (((JBooleanLiteral) condExpr).getValue()) {
        // e.g. (true ? then : else) -> then
        return thenExpr;
      } else {
        // e.g. (false ? then : else) -> else
        return elseExpr;
      }
    } else if (thenExpr instanceof JBooleanLiteral) {
      if (((JBooleanLiteral) thenExpr).getValue()) {
        // e.g. (cond ? true : else) -> cond || else
        return orImpl(null, info, condExpr, elseExpr);
      } else {
        // e.g. (cond ? false : else) -> !cond && else
        JExpression notCondExpr = notImpl(null, condExpr.getSourceInfo(), condExpr);
        return andImpl(null, info, notCondExpr, elseExpr);
      }
    } else if (elseExpr instanceof JBooleanLiteral) {
      if (((JBooleanLiteral) elseExpr).getValue()) {
        // e.g. (cond ? then : true) -> !cond || then
        JExpression notCondExpr = notImpl(null, condExpr.getSourceInfo(), condExpr);
        return orImpl(null, info, notCondExpr, thenExpr);
      } else {
        // e.g. (cond ? then : false) -> cond && then
        return andImpl(null, info, condExpr, thenExpr);
      }
    } else {
      // e.g. (!cond ? then : else) -> (cond ? else : then)
      JExpression unflipped = maybeUnflipBoolean(condExpr);
      if (unflipped != null) {
        return new JConditional(info, type, unflipped, elseExpr, thenExpr);
      }
    }

    // no simplification made
    if (original != null) {
      return original;
    }
    return new JConditional(info, type, condExpr, thenExpr, elseExpr);
  }

  /**
   * Simplifies an ifthenelse statement.
   *
   * <pre>
   * if(a,b,c) d [else e] -> {a; b; if(c) d [else e]; }
   * if(true) a [else b] -> a
   * if(false) a else b -> b
   * if(notImpl(c)) a else b -> if(c) b else a
   * if(true) ; else b -> true
   * if(false) a [else ;] -> false
   * if(c) ; [else ;] -> c
   *</pre>
   *
   * @param stmt the statement to simplify.
   * @param currentMethod the method where the statement resides
   * @return the simplified statement if a simplification could be done and <code>stmt</code>
   *         otherwise.
   */
  public static JStatement ifStatement(JIfStatement stmt,  JMethod currentMethod) {
    return ifStatementImpl(stmt, stmt.getSourceInfo(), stmt.getIfExpr(),
        stmt.getThenStmt(), stmt.getElseStmt(), currentMethod);
  }

  private static JStatement ifStatementImpl(JIfStatement original, SourceInfo info,
      JExpression condExpr, JStatement thenStmt,JStatement elseStmt, JMethod currentMethod) {
    info = getBestSourceInfo(original, info, condExpr);
    if (condExpr instanceof JMultiExpression) {
      // if(a,b,c) d else e -> {a; b; if(c) d else e; }
      JMultiExpression condMulti = (JMultiExpression) condExpr;
      JBlock newBlock = new JBlock(info);
      for (JExpression expr : allButLast(condMulti.getExpressions())) {
        newBlock.addStmt(expr.makeStatement());
      }
      newBlock.addStmt(ifStatementImpl(null, info, last(condMulti.getExpressions()), thenStmt,
          elseStmt, currentMethod));
      // TODO(spoon): immediately simplify the resulting block
      return newBlock;
    }

    if (condExpr instanceof JBooleanLiteral) {
      JBooleanLiteral booleanLiteral = (JBooleanLiteral) condExpr;
      boolean boolVal = booleanLiteral.getValue();
      if (boolVal && !isEmpty(thenStmt)) {
        // If true, replace myself with then statement
        return thenStmt;
      } else if (!boolVal && !isEmpty(elseStmt)) {
        // If false, replace myself with else statement
        return elseStmt;
      } else {
        // just prune me
        return condExpr.makeStatement();
      }
    }

    if (isEmpty(thenStmt) && isEmpty(elseStmt)) {
      return condExpr.makeStatement();
    }

    if (!isEmpty(elseStmt)) {
      // if (!cond) foo else bar -> if (cond) bar else foo
      JExpression unflipped = Simplifier.maybeUnflipBoolean(condExpr);
      if (unflipped != null) {
        // Force sub-parts to blocks, otherwise we break else-if chains.
        // TODO: this goes away when we normalize the Java AST properly.
        thenStmt = ensureBlock(thenStmt);
        elseStmt = ensureBlock(elseStmt);
        return ifStatementImpl(null, info, unflipped, elseStmt, thenStmt, currentMethod);
      }
    }

    JStatement rewritenStatement =
        rewriteIfIntoBoolean(info, condExpr, thenStmt, elseStmt, currentMethod);
    if (rewritenStatement != null) {
      return rewritenStatement;
    }

    // no simplification made
    if (original != null) {
      return original;
    }
    return new JIfStatement(info, condExpr, thenStmt, elseStmt);
  }

  /**
   * Simplifies an negation expression.
   *
   * if(a,b,c) d else e -> {a; b; if(c) d else e; }
   *
   * @param expr the expression to simplify.
   * @return the simplified expression if a simplification could be done and <code>expr</code>
   *         otherwise.
   */
  public static JExpression not(JPrefixOperation expr) {
    return notImpl(expr, expr.getSourceInfo(), expr.getArg());
  }

  private static JExpression notImpl(JPrefixOperation original, SourceInfo info, JExpression arg) {
    info = getBestSourceInfo(original, info, arg);
    if (arg instanceof JMultiExpression) {
      // !(a,b,c) -> (a,b,!c)
      JMultiExpression argMulti = (JMultiExpression) arg;
      JMultiExpression newMulti = new JMultiExpression(info);
      newMulti.addExpressions(allButLast(argMulti.getExpressions()));
      newMulti.addExpressions(notImpl(null, info, last(argMulti.getExpressions())));
      // TODO(spoon): immediately simplify the newMulti
      return newMulti;
    }
    if (arg instanceof JBinaryOperation) {
      // try to invert the binary operator
      JBinaryOperation argOp = (JBinaryOperation) arg;
      JBinaryOperator op = argOp.getOp();
      JBinaryOperator newOp = null;
      if (op == JBinaryOperator.EQ) {
        // e.g. !(x == y) -> x != y
        newOp = JBinaryOperator.NEQ;
      } else if (op == JBinaryOperator.NEQ) {
        // e.g. !(x != y) -> x == y
        newOp = JBinaryOperator.EQ;
      } else if (op == JBinaryOperator.GT) {
        // e.g. !(x > y) -> x <= y
        newOp = JBinaryOperator.LTE;
      } else if (op == JBinaryOperator.LTE) {
        // e.g. !(x <= y) -> x > y
        newOp = JBinaryOperator.GT;
      } else if (op == JBinaryOperator.GTE) {
        // e.g. !(x >= y) -> x < y
        newOp = JBinaryOperator.LT;
      } else if (op == JBinaryOperator.LT) {
        // e.g. !(x < y) -> x >= y
        newOp = JBinaryOperator.GTE;
      }
      if (newOp != null) {
        JBinaryOperation newBinOp =
            new JBinaryOperation(info, argOp.getType(), newOp, argOp.getLhs(), argOp.getRhs());
        return newBinOp;
      }
    } else if (arg instanceof JPrefixOperation) {
      // try to invert the unary operator
      JPrefixOperation argOp = (JPrefixOperation) arg;
      JUnaryOperator op = argOp.getOp();
      // e.g. !!x -> x
      if (op == JUnaryOperator.NOT) {
        return argOp.getArg();
      }
    } else if (arg instanceof JBooleanLiteral) {
      JBooleanLiteral booleanLit = (JBooleanLiteral) arg;
      return JBooleanLiteral.get(!booleanLit.getValue());
    }

    // no simplification made
    if (original != null) {
      return original;
    }
    return new JPrefixOperation(info, JUnaryOperator.NOT, arg);
  }

  /**
   * Simplify short circuit AND expressions.
   *
   * <pre>
   * true && isWhatever() -> isWhatever()
   * false && isWhatever() -> false
   *
   * isWhatever() && true -> isWhatever()
   * isWhatever() && false -> false, unless side effects
   *
   * (a, b) && c -> (a, b && c)
   * </pre>
   *
   * @param exp an AND JBinaryExpression to be simplified.
   * @return the simplified expression if a simplification was possible; <code>exp</code> otherwise.
   *
   */
  public static JExpression and(JBinaryOperation exp) {
    assert exp.getOp() == JBinaryOperator.AND : "Simplifier.and was called with " + exp;
    return andImpl(exp, null, exp.getLhs(), exp.getRhs());
  }

  private static JExpression andImpl(JBinaryOperation original, SourceInfo info, JExpression lhs,
      JExpression rhs) {
    info = getBestSourceInfo(original, info, lhs);
    if (lhs instanceof JMultiExpression) {
      // (a,b,c)&&d -> a,b,(c&&d)
      JMultiExpression lhsMulti = (JMultiExpression) lhs;
      JMultiExpression newMulti = new JMultiExpression(info);
      newMulti.addExpressions(allButLast(lhsMulti.getExpressions()));
      newMulti.addExpressions(andImpl(null, info, last(lhsMulti.getExpressions()), rhs));
      // TODO(rluble): immediately simplify the resulting multi.
      // TODO(rluble): refactor common outward JMultiExpression movement.
      return newMulti;
    }
    if (lhs instanceof JBooleanLiteral) {
      JBooleanLiteral booleanLiteral = (JBooleanLiteral) lhs;
      if (booleanLiteral.getValue()) {
        return rhs;
      } else {
        return lhs;
      }

    } else if (rhs instanceof JBooleanLiteral) {
      JBooleanLiteral booleanLiteral = (JBooleanLiteral) rhs;
      if (booleanLiteral.getValue()) {
        return lhs;
      } else if (!lhs.hasSideEffects()) {
        return rhs;
      }
    }
    // no simplification made
    if (original != null) {
      return original;
    }
    return new JBinaryOperation(info, rhs.getType(), JBinaryOperator.AND, lhs, rhs);
  }

  /**
   * Simplify short circuit OR expressions.
   *
   * <pre>
   * true || isWhatever() -> true
   * false || isWhatever() -> isWhatever()
   *
   * isWhatever() || false isWhatever()
   * isWhatever() || true -> true, unless side effects
   *
   * (a, b) || c -> (a, b || c)
   * </pre>
   *
   * @param exp an OR JBinaryExpression to be simplified.
   * @return the simplified expression if a simplification was possible; <code>exp</code> otherwise.
   *
   */
  public static JExpression or(JBinaryOperation exp) {
    assert exp.getOp() == JBinaryOperator.OR : "Simplifier.and was called with " + exp;
    return orImpl(exp, null, exp.getLhs(), exp.getRhs());
  }

  private static JExpression orImpl(JBinaryOperation original, SourceInfo info, JExpression lhs,
      JExpression rhs) {
    info = getBestSourceInfo(original, info, lhs);
    if (lhs instanceof JMultiExpression) {
      // (a,b,c)|| d -> a,b,(c||d)
      JMultiExpression lhsMulti = (JMultiExpression) lhs;
      JMultiExpression newMulti = new JMultiExpression(info);
      newMulti.addExpressions(allButLast(lhsMulti.getExpressions()));
      newMulti.addExpressions(orImpl(null, info, last(lhsMulti.getExpressions()), rhs));
      // TODO(rluble): immediately simplify the resulting multi.
      // TODO(rluble): refactor common outward JMultiExpression movement.
      return newMulti;
    }
    if (lhs instanceof JBooleanLiteral) {
      JBooleanLiteral booleanLiteral = (JBooleanLiteral) lhs;
      if (booleanLiteral.getValue()) {
        return lhs;
      } else {
        return rhs;
      }
    } else if (rhs instanceof JBooleanLiteral) {
      JBooleanLiteral booleanLiteral = (JBooleanLiteral) rhs;
      if (!booleanLiteral.getValue()) {
        return lhs;
      } else if (!lhs.hasSideEffects()) {
        return rhs;
      }
    }
    // no simplification made
    if (original != null) {
      return original;
    }
    return new JBinaryOperation(info, rhs.getType(), JBinaryOperator.OR, lhs, rhs);
  }

  private static JStatement ensureBlock(JStatement stmt) {
    if (stmt == null) {
      return null;
    }
    if (!(stmt instanceof JBlock)) {
      JBlock block = new JBlock(stmt.getSourceInfo());
      block.addStmt(stmt);
      stmt = block;
    }
    return stmt;
  }

  private static JExpression extractExpression(JStatement stmt) {
    if (stmt instanceof JExpressionStatement) {
      JExpressionStatement statement = (JExpressionStatement) stmt;
      return statement.getExpr();
    }

    return null;
  }

  private static JStatement extractSingleStatement(JStatement stmt) {
    if (stmt instanceof JBlock) {
      JBlock block = (JBlock) stmt;
      if (block.getStatements().size() == 1) {
        return extractSingleStatement(block.getStatements().get(0));
      }
    }

    return stmt;
  }

  /**
   * Determine the best SourceInfo to use in a particular transformation.
   *
   * @param original the original node that is being transformed. Can be <code>null</code>.
   * @param info an explicit SourceInfo that might be used, Can be <code>null</code>.
   * @param defaultNode a node from where to obtain the SourceInfo.
   * @return a SourceInfo chosen according to the following priority info>original>default.
   */
  private static SourceInfo getBestSourceInfo(JNode original, SourceInfo info, JNode defaultNode) {
    if (info == null) {
      if (original == null) {
        info = defaultNode.getSourceInfo();
      } else {
        info = original.getSourceInfo();
      }
    }
    return info;
  }

  private static JStatement rewriteIfIntoBoolean(SourceInfo sourceInfo, JExpression condExpr,
      JStatement thenStmt, JStatement elseStmt, JMethod currentMethod) {
    thenStmt = extractSingleStatement(thenStmt);
    elseStmt = extractSingleStatement(elseStmt);

    if (thenStmt instanceof JReturnStatement && elseStmt instanceof JReturnStatement
        && currentMethod != null) {
      // Special case
      // if () { return ..; } else { return ..; } =>
      // return ... ? ... : ...;
      JExpression thenExpression = ((JReturnStatement) thenStmt).getExpr();
      JExpression elseExpression = ((JReturnStatement) elseStmt).getExpr();
      if (thenExpression == null || elseExpression == null) {
        // empty returns are not supported.
        return null;
      }

      JConditional conditional =
          new JConditional(sourceInfo, currentMethod.getType(), condExpr, thenExpression,
              elseExpression);

      JReturnStatement returnStatement = conditional.makeReturnStatement();
      return returnStatement;
    }

    if (elseStmt != null) {
      // if () { } else { } -> ... ? ... : ... ;
      JExpression thenExpression = extractExpression(thenStmt);
      JExpression elseExpression = extractExpression(elseStmt);

      if (thenExpression != null && elseExpression != null) {
        JConditional conditional =
            new JConditional(sourceInfo, JPrimitiveType.VOID, condExpr, thenExpression,
                elseExpression);

        return conditional.makeStatement();
      }
    } else {
      // if () { } -> ... && ...;
      JExpression thenExpression = extractExpression(thenStmt);

      if (thenExpression != null) {
        JBinaryOperator binaryOperator = JBinaryOperator.AND;

        JExpression unflipExpression = maybeUnflipBoolean(condExpr);
        if (unflipExpression != null) {
          condExpr = unflipExpression;
          binaryOperator = JBinaryOperator.OR;
        }

        JBinaryOperation binaryOperation =
            new JBinaryOperation(sourceInfo, JPrimitiveType.VOID, binaryOperator, condExpr,
                thenExpression);

        return binaryOperation.makeStatement();
      }
    }

    return null;
  }
}
