/*
 * 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.SourceOrigin;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.HasName;
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.JCastMap;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
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.JTypeOracle;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.thirdparty.guava.common.collect.HashMultimap;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Builds minimal cast maps to cover cast and instanceof operations. Depends
 * on {@link CatchBlockNormalizer}, {@link CompoundAssignmentNormalizer},
 * {@link Devirtualizer}, and {@link LongCastNormalizer} having already run.
 * <p>
 * May or may not include trivial casts depending on configuration.
 */
public class ComputeCastabilityInformation {
  private class AssignTypeCastabilityVisitor extends JVisitor {

    private final Set<JReferenceType> alreadyRan = Sets.newHashSet();
    private final Map<JReferenceType, JCastMap> castableTypesMap = Maps.newIdentityHashMap();
    private final List<JArrayType> instantiatedArrayTypes = Lists.newArrayList();
    private final Multimap<JReferenceType, JReferenceType> castSourceTypesPerCastTargetType =
        HashMultimap.create();

    {
      for (JArrayType arrayType : program.getAllArrayTypes()) {
        if (typeOracle.isInstantiatedType(arrayType)) {
          instantiatedArrayTypes.add(arrayType);
        }
      }

      // Force entries for Object and String.
      recordCastInternal(program.getTypeJavaLangObject(), program.getTypeJavaLangObject());
      recordCastInternal(program.getTypeJavaLangString(), program.getTypeJavaLangObject());

      // Force entries for interfaces implemented by  String
      recordCastInternal(program.getIndexedType("Serializable"), program.getTypeJavaLangObject());
      recordCastInternal(program.getIndexedType("CharSequence"), program.getTypeJavaLangObject());
      recordCastInternal(program.getIndexedType("Comparable"), program.getTypeJavaLangObject());
    }

    public void computeTypeCastabilityMaps() {
      // do String first (which will pull in Object also, it's superclass).
      computeCastMap(program.getTypeJavaLangString());
      assert (castableTypesMap.size() == 2);

      /*
       * Compute the list of classes than can successfully satisfy cast
       * requests, along with the set of types they can be successfully cast to.
       * Do it in super type order.
       */
      for (JReferenceType type : program.getDeclaredTypes()) {
        if (type instanceof JClassType) {
          computeCastMap(type);
        }
      }

      for (JArrayType type : instantiatedArrayTypes) {
        computeCastMap(type);
      }

      // pass our info to JProgram
      program.initTypeInfo(castableTypesMap);
    }

    /*
     * If this expression could possibly generate an ArrayStoreException, we
     * must record a query on the element type being assigned to.
     */
    @Override
    public void endVisit(JBinaryOperation x, Context ctx) {
      if (!x.getOp().isAssignment() || !(x.getLhs() instanceof JArrayRef)) {
        return;
      }

      // first, calculate the transitive closure of all possible runtime types
      // the lhs could be
      JArrayRef lhsArrayRef = (JArrayRef) x.getLhs();
      JType elementType = lhsArrayRef.getType();
      if (elementType.isNullType()) {
        // will generate a null pointer exception instead
        return;
      }

      // primitives are statically correct
      if (!(elementType instanceof JReferenceType)) {
        return;
      }

      // This array reference always refers to an array of the declared class, not a subclass.
      if (!lhsArrayRef.getInstance().getType().canBeSubclass()) {
        return;
      }

      /*
       * For every instantiated array type that could -in theory- be the
       * runtime type of the lhs, we must record a cast from the rhs to the
       * prospective element type of the lhs.
       */
      JType rhsType = x.getRhs().getType();
      assert (rhsType instanceof JReferenceType);

      JArrayType lhsArrayType = lhsArrayRef.getArrayType();
      for (JArrayType arrayType : instantiatedArrayTypes) {
        if (!typeOracle.castFailsTrivially(arrayType, lhsArrayType)) {
          JType itElementType = arrayType.getElementType();
          if (itElementType instanceof JReferenceType) {
            recordCast(itElementType, x.getRhs());
          }
        }
      }
    }

    @Override
    public void endVisit(JCastOperation x, Context ctx) {
      if (x.getCastType().isNullType()) {
        return;
      }
      recordCast(x.getCastType(), x.getExpr());
    }

    @Override
    public void endVisit(JInstanceOf x, Context ctx) {
      assert (!x.getTestType().isNullType());
      recordCast(x.getTestType(), x.getExpr());
    }

    /**
     * Returns true if the cast *might* succeed at runtime considering the semantics of JSO casts.
     */
    private boolean castSucceedsTriviallyJsoSemantics(
        JReferenceType fromType, JReferenceType toType) {

      fromType = fromType.getUnderlyingType();
      toType = toType.getUnderlyingType();

      if (typeOracle.castSucceedsTrivially(fromType, toType)) {
        return true;
      }

      // Casting to a native type might succeed (even in cases where the same cast would never
      // succeed in the Java type system, due to JSOs and native JsType sematics).
      if (toType.isJsNative()) {
        return true;
      }

      if (fromType instanceof JArrayType && toType instanceof JArrayType) {
        JArrayType fromArrayType = (JArrayType) fromType;
        JArrayType toArrayType = (JArrayType) toType;
        return (fromArrayType.getLeafType().isJsoType() &&
            toArrayType.getLeafType().isJsoType());
      }

      return fromType.isJsoType() && toType.isJsoType();
    }

    /**
     * Create the mapping from a class to the types it can be cast to.
     */
    private void computeCastMap(JReferenceType type) {
      if (type == null || alreadyRan.contains(type)) {
        return;
      }
      assert (type == type.getUnderlyingType());

      alreadyRan.add(type);

      // Visit super type.
      if (type instanceof JClassType) {
        computeCastMap(((JClassType) type).getSuperClass());
      }

      if (!typeOracle.isInstantiatedType(type) ||
          type.isJsoType() || type.isJsNative()) {
        return;
      }

      // Find all possible query types which I can satisfy
      Set<JReferenceType> castableTypes = Sets.newTreeSet(HasName.BY_NAME_COMPARATOR);

      /*
       * NOTE: non-deterministic iteration over HashSet and HashMap. Okay
       * because we're sorting the results.
       */
      for (JReferenceType castTargetType : castSourceTypesPerCastTargetType.keySet()) {
        if (!castSucceedsTriviallyJsoSemantics(type, castTargetType)) {
          // Cannot cast type to castTargetType, hence no entry in the cast map.
          continue;
        }

        Collection<JReferenceType> castSourceTypes =
            castSourceTypesPerCastTargetType.get(castTargetType);
        /**
         * Handles JSO[] -> JSO[] case now that canCastTrivially doesn't deal
         * with JSO cross-casts anymore.
         */
        for (JReferenceType castSourceType : castSourceTypes) {
          if (castSucceedsTriviallyJsoSemantics(type, castSourceType)) {
            boolean isTrivialCast = castTargetType == program.getTypeJavaLangObject()
                || castTargetType == program.getJavaScriptObject();
            if (recordTrivialCasts || !isTrivialCast) {
              castableTypes.add(castTargetType);
            }
            break;
          }
        }
      }

      /*
       * Don't add an entry for empty answer sets, except for Object and String
       * which require entries.
       */
      if (castableTypes.isEmpty() && type != program.getTypeJavaLangObject()
          && type != program.getTypeJavaLangString()) {
        return;
      }

      // add an entry for me
      castableTypesMap.put(type, new JCastMap(SourceOrigin.UNKNOWN, program.getTypeJavaLangObject(),
          Collections.unmodifiableSet(castableTypes)));
    }

    private void recordCast(JType targetType, JExpression rhs) {
      if (!(targetType instanceof JReferenceType) || targetType.isJsNative()) {
        return;
      }
      targetType = targetType.getUnderlyingType();
      assert rhs.getType() instanceof JReferenceType;

      JReferenceType rhsType = (JReferenceType) rhs.getType().getUnderlyingType();
      if (!recordTrivialCasts
          && typeOracle.castSucceedsTrivially(rhsType, (JReferenceType) targetType)) {
        // don't record a type for trivial casts that won't generate code
        return;
      }

      if (!recordTrivialCasts && targetType.isJsoType()) {
        // If the target type is a JavaScriptObject, don't record an id.
        return;
      }

      recordCastInternal((JReferenceType) targetType, rhsType);
    }

    private void recordCastInternal(JReferenceType toType, JReferenceType rhsType) {
      toType = toType.getUnderlyingType();
      rhsType = rhsType.getUnderlyingType();

      if (toType instanceof JArrayType) {
        // Arrays of any subclass of JavaScriptObject are considered arrays of JavaScriptObject
        // for casting and instanceof purposes.
        toType =  (JReferenceType) program.normalizeJsoType(toType);
      }

      castSourceTypesPerCastTargetType.put(toType, rhsType);
    }
  }

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

  public static void exec(JProgram program) {
    new ComputeCastabilityInformation(program, false).execImpl();
  }

  private final boolean recordTrivialCasts;

  private final JProgram program;

  private final JTypeOracle typeOracle;

  private ComputeCastabilityInformation(JProgram program, boolean recordTrivialCasts) {
    this.program = program;
    this.typeOracle = program.typeOracle;
    this.recordTrivialCasts = recordTrivialCasts;
  }

  private void execImpl() {
    AssignTypeCastabilityVisitor assigner = new AssignTypeCastabilityVisitor();
    assigner.accept(program);
    assigner.computeTypeCastabilityMaps();
  }
}
