/*
 * Copyright 2007 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.Context;
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.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JIfStatement;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JThrowStatement;
import com.google.gwt.dev.jjs.ast.JTryStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.RuntimeConstants;

import java.util.ArrayList;
import java.util.List;

/**
 * Merge multi-catch blocks into a single catch block that uses instanceof tests
 * to determine which user block to run.
 */
public class CatchBlockNormalizer {

  /**
   * Collapses all multi-catch blocks into a single catch block.
   */
  private class CollapseCatchBlocks extends JModVisitor {
    JMethod wrapMethod = program.getIndexedMethod(RuntimeConstants.EXCEPTIONS_TO_JAVA);

    @Override
    public void endVisit(JMethodBody x, Context ctx) {
      clearLocals();
      currentMethodBody = null;
    }

    @Override
    public void endVisit(JTryStatement x, Context ctx) {
      if (x.getCatchClauses().isEmpty() &&
          (x.getFinallyBlock() == null || x.getFinallyBlock().isEmpty())) {
        // Remove {@code try { ...  }} if there are not catch and/or finally blocks. Translating it
        // to JavaScript as {@code try { ... }} without catch and/or finally is illegal.
        ctx.replaceMe(x.getTryBlock());
      }

      if (x.getCatchClauses().isEmpty()) {
        return;
      }

      SourceInfo catchInfo = x.getCatchClauses().get(0).getBlock().getSourceInfo();
      JLocal exceptionVariable = newExceptionVariable(x.getSourceInfo());
      JBlock newCatchBlock = new JBlock(catchInfo);

      {
        // $e = Exceptions.toJava($e)
        JMethodCall call =
            new JMethodCall(catchInfo, null, wrapMethod, exceptionVariable.makeRef(catchInfo));
        newCatchBlock.addStmt(
            JProgram.createAssignmentStmt(catchInfo, exceptionVariable.makeRef(catchInfo), call));
      }

      /*
       * Build up a series of if, else if statements to test the type of the
       * exception object against the types of the user's catch block. Each catch block might have
       * multiple types in Java 7.
       *
       * Go backwards so we can nest the else statements in the correct order!
       */
      // rethrow the current exception if no one caught it.
      JStatement cur = new JThrowStatement(catchInfo, exceptionVariable.makeRef(catchInfo));
      for (int i = x.getCatchClauses().size() - 1; i >= 0; i--) {
        JTryStatement.CatchClause clause = x.getCatchClauses().get(i);
        JBlock block = clause.getBlock();
        JLocalRef arg = clause.getArg();
        List<JType> exceptionsTypes = clause.getTypes();
        catchInfo = block.getSourceInfo();

        // if ($e instanceof ArgType1 or $e instanceof ArgType2 ...) {
        //   var userVar = $e; <user code>
        // }

        // Handle the first Exception type.
        JExpression ifTest = new JInstanceOf(catchInfo, (JReferenceType) exceptionsTypes.get(0),
            exceptionVariable.makeRef(catchInfo));
        // Handle the rest of the Exception types if any.
        for (int j = 1; j < exceptionsTypes.size(); j++) {
          JExpression orExp = new JInstanceOf(catchInfo, (JReferenceType) exceptionsTypes.get(j),
              exceptionVariable.makeRef(catchInfo));
          ifTest = new JBinaryOperation(catchInfo, JPrimitiveType.BOOLEAN, JBinaryOperator.OR,
              ifTest, orExp);
        }
        JDeclarationStatement declaration =
            new JDeclarationStatement(catchInfo, arg, exceptionVariable.makeRef(catchInfo));
        block.addStmt(0, declaration);
        // nest the previous as an else for me
        cur = new JIfStatement(catchInfo, ifTest, block, cur);
      }

      newCatchBlock.addStmt(cur);

      // Replace with a single catch block.
      x.getCatchClauses().clear();
      List<JType> newCatchTypes = new ArrayList<JType>(1);
      newCatchTypes.add(exceptionVariable.getType());
      x.getCatchClauses().add(new JTryStatement.CatchClause(newCatchTypes,
          exceptionVariable.makeRef(catchInfo), newCatchBlock));
    }

    @Override
    public boolean visit(JMethodBody x, Context ctx) {
      currentMethodBody = x;
      clearLocals();
      return true;
    }
  }

  private class UnwrapThrowableVisitor extends JModVisitor {
    JMethod unwrapMethod = program.getIndexedMethod(RuntimeConstants.EXCEPTIONS_TO_JS);

    @Override
    public void endVisit(JThrowStatement x, Context ctx) {
      // throw x; -> throw Exceptions.toJs(x);
      ctx.replaceMe(createUnwrappedThrow(x));
    }

    private JThrowStatement createUnwrappedThrow(JThrowStatement x) {
      JMethodCall call = new JMethodCall(x.getSourceInfo(), null, unwrapMethod);
      call.addArg(x.getExpr());
      return new JThrowStatement(x.getSourceInfo(), call);
    }
  }

  public static void exec(JProgram program) {
    new CatchBlockNormalizer(program).execImpl();
  }

  private JMethodBody currentMethodBody;
  private int catchVariableIndex;
  private final JProgram program;

  private CatchBlockNormalizer(JProgram program) {
    this.program = program;
  }

  private void clearLocals() {
    catchVariableIndex = 0;
  }

  private void execImpl() {
    CollapseCatchBlocks collapser = new CollapseCatchBlocks();
    collapser.accept(program);
    UnwrapThrowableVisitor unwrapper = new UnwrapThrowableVisitor();
    unwrapper.accept(program);
  }

  private JLocal newExceptionVariable(SourceInfo sourceInfo) {
    return JProgram.createLocal(sourceInfo, "$e" + catchVariableIndex++,
        program.getTypeJavaLangObject(), false, currentMethodBody);
  }
}
