/*
 * 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.Context;
import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension;
import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JIntLiteral;
import com.google.gwt.dev.jjs.ast.JLiteral;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNewArray;
import com.google.gwt.dev.jjs.ast.JNullType;
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.JType;
import com.google.gwt.dev.jjs.ast.js.JsCastMap;
import com.google.gwt.dev.jjs.ast.js.JsCastMap.JsQueryType;
import com.google.gwt.dev.jjs.ast.js.JsonArray;
import com.google.gwt.dev.util.collect.Lists;

/**
 * Replace array accesses and instantiations with calls to the Array class.
 * Depends on {@link CompoundAssignmentNormalizer} and {@link CastNormalizer}
 * having already run.
 */
public class ArrayNormalizer {

  private class ArrayVisitor extends JModVisitor {

    @Override
    public void endVisit(JBinaryOperation x, Context ctx) {
      if (x.getOp() == JBinaryOperator.ASG && x.getLhs() instanceof JArrayRef) {
        JArrayRef arrayRef = (JArrayRef) x.getLhs();
        JType elementType = arrayRef.getType();
        if (elementType instanceof JNullType) {
          // will generate a null pointer exception instead
          return;
        }

        /*
         * See if we need to do a checked store. Primitives and (effectively)
         * final are statically correct.
         */
        if (!disableCastChecking) {
          if (elementType instanceof JReferenceType) {
            if (!((JReferenceType) elementType).isFinal() || !program.typeOracle.canTriviallyCast(
                (JReferenceType) x.getRhs().getType(), (JReferenceType) elementType)) {
              // replace this assignment with a call to setCheck()
              JMethodCall call = new JMethodCall(x.getSourceInfo(), null, setCheckMethod);
              call.addArgs(arrayRef.getInstance(), arrayRef.getIndexExpr(), x.getRhs());
              ctx.replaceMe(call);
            }
          }
        }
      }
    }

    @Override
    public void endVisit(JNewArray x, Context ctx) {
      JArrayType type = x.getArrayType();

      if (x.initializers != null) {
        processInitializers(x, ctx, type);
      } else {
        int realDims = 0;
        for (JExpression dim : x.dims) {
          if (dim instanceof JAbsentArrayDimension) {
            break;
          }
          ++realDims;
        }
        assert (realDims >= 1);
        if (realDims == 1) {
          processDim(x, ctx, type);
        } else {
          processDims(x, ctx, type, realDims);
        }
      }
    }

    private JsQueryType getElementQueryType(SourceInfo sourceInfo, JArrayType arrayType) {
      JType elementType = arrayType.getElementType();
      int elementQueryId = -1;
      if (elementType instanceof JReferenceType) {
        JReferenceType elementRefType = (JReferenceType) elementType;
        elementType = elementRefType.getUnderlyingType();
        if (program.typeOracle.isEffectivelyJavaScriptObject(elementRefType)) {
          /*
           * treat types that are effectively JSO's as JSO's, for the purpose of
           * castability checking
           */
          elementRefType = program.getJavaScriptObject();
        }  
        elementQueryId = program.getQueryId(elementRefType);
        if (program.typeOracle.isDualJsoInterface(elementRefType)) {
          /*
           * invert the queryId, to indicate dual castability for JSO's and the
           * Java type represented by the inverse of the queryId
           */
          elementQueryId *= -1;
        }
      }
      return new JsQueryType(sourceInfo, elementType, elementQueryId);
    }

    private JExpression getOrCreateCastMap(SourceInfo sourceInfo, JArrayType arrayType) {
      JsCastMap castableTypeMap = program.getCastMap(arrayType);
      if (castableTypeMap == null || castableTypeMap.getExprs().size() == 0) {
        return new JsCastMap(sourceInfo, Lists.<JsQueryType>create(), program.getJavaScriptObject());
      }
      return castableTypeMap;
    }

    /**
     * @see com.google.gwt.lang.Array regarding seed types
     */
    private JIntLiteral getSeedTypeLiteralFor(JType type) {
      if (type instanceof JPrimitiveType) {
        if (type == program.getTypePrimitiveLong()) {
          // The long type, thus 0L (index 3)
          return program.getLiteralInt(3);
        } else if (type == program.getTypePrimitiveBoolean()) {
          // The boolean type, thus false (index 2)
          return program.getLiteralInt(2);
        } else {
          // A numeric type, thus zero (index 1).
          return program.getLiteralInt(1);
        }
      }
      // An Object type, thus null (index 0).
      return program.getLiteralInt(0);
    }

    private void processDim(JNewArray x, Context ctx, JArrayType arrayType) {
      // override the type of the called method with the array's type
      SourceInfo sourceInfo = x.getSourceInfo();
      JMethodCall call = new JMethodCall(sourceInfo, null, initDim, arrayType);
      JLiteral classLit = x.getClassLiteral();
      JExpression castableTypeMap = getOrCreateCastMap(sourceInfo, arrayType);
      JLiteral queryIdLit = getElementQueryType(sourceInfo, arrayType);
      JExpression dim = x.dims.get(0);
      JType elementType = arrayType.getElementType();
      call.addArgs(classLit, castableTypeMap, queryIdLit, dim, getSeedTypeLiteralFor(elementType));
      ctx.replaceMe(call);
    }

    private void processDims(JNewArray x, Context ctx, JArrayType arrayType, int dims) {
      // override the type of the called method with the array's type
      SourceInfo sourceInfo = x.getSourceInfo();
      JMethodCall call = new JMethodCall(sourceInfo, null, initDims, arrayType);
      JsonArray classLitList = new JsonArray(sourceInfo, program.getJavaScriptObject());
      JsonArray castableTypeMapList = new JsonArray(sourceInfo, program.getJavaScriptObject());
      JsonArray queryIdList = new JsonArray(sourceInfo, program.getJavaScriptObject());
      JsonArray dimList = new JsonArray(sourceInfo, program.getJavaScriptObject());
      JType cur = arrayType;
      for (int i = 0; i < dims; ++i) {
        // Walk down each type from most dims to least.
        JArrayType curArrayType = (JArrayType) cur;

        JLiteral classLit = x.getClassLiterals().get(i);
        classLitList.getExprs().add(classLit);

        JExpression castableTypeMap = getOrCreateCastMap(sourceInfo, curArrayType);
        castableTypeMapList.getExprs().add(castableTypeMap);

        JLiteral queryIdLit = getElementQueryType(sourceInfo, curArrayType);
        queryIdList.getExprs().add(queryIdLit);

        dimList.getExprs().add(x.dims.get(i));
        cur = curArrayType.getElementType();
      }
      call.addArgs(classLitList, castableTypeMapList, queryIdList, dimList, program
          .getLiteralInt(dims), getSeedTypeLiteralFor(cur));
      ctx.replaceMe(call);
    }

    private void processInitializers(JNewArray x, Context ctx, JArrayType arrayType) {
      // override the type of the called method with the array's type
      SourceInfo sourceInfo = x.getSourceInfo();
      JMethodCall call = new JMethodCall(sourceInfo, null, initValues, arrayType);
      JLiteral classLit = x.getClassLiteral();
      JExpression castableTypeMap = getOrCreateCastMap(sourceInfo, arrayType);
      JLiteral queryIdLit = getElementQueryType(sourceInfo, arrayType);
      JsonArray initList = new JsonArray(sourceInfo, program.getJavaScriptObject());
      for (int i = 0; i < x.initializers.size(); ++i) {
        initList.getExprs().add(x.initializers.get(i));
      }
      call.addArgs(classLit, castableTypeMap, queryIdLit, initList);
      ctx.replaceMe(call);
    }
  }

  public static void exec(JProgram program, boolean disableCastChecking) {
    new ArrayNormalizer(program, disableCastChecking).execImpl();
  }

  private final boolean disableCastChecking;
  private final JMethod initDim;
  private final JMethod initDims;
  private final JMethod initValues;
  private final JProgram program;
  private final JMethod setCheckMethod;

  private ArrayNormalizer(JProgram program, boolean disableCastChecking) {
    this.program = program;
    this.disableCastChecking = disableCastChecking;
    setCheckMethod = program.getIndexedMethod("Array.setCheck");

    initDim = program.getIndexedMethod("Array.initDim");
    initDims = program.getIndexedMethod("Array.initDims");
    initValues = program.getIndexedMethod("Array.initValues");
  }

  private void execImpl() {
    ArrayVisitor visitor = new ArrayVisitor();
    visitor.accept(program);
  }

}
