/*
 * 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 instanceof JPrimitiveType) && (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;
  }
}
