/*
 * Copyright 2013 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.test;

import com.google.gwt.dev.jjs.test.overrides.package1.Caller;
import com.google.gwt.dev.jjs.test.overrides.package1.ClassExposingM;
import com.google.gwt.dev.jjs.test.overrides.package1.SomeParent;
import com.google.gwt.dev.jjs.test.overrides.package1.SomeParentParent;
import com.google.gwt.dev.jjs.test.overrides.package1.SomeParentParentParent;
import com.google.gwt.dev.jjs.test.overrides.package1.SubClassExposingM;
import com.google.gwt.dev.jjs.test.overrides.package2.SomeSubClassInAnotherPackage;
import com.google.gwt.dev.jjs.test.overrides.package2.SomeSubSubClassInAnotherPackage;
import com.google.gwt.dev.jjs.test.overrides.package3.SomeInterface;
import com.google.gwt.dev.jjs.test.overrides.package3.SomePackageConfusedParent;
import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
import com.google.gwt.junit.client.GWTTestCase;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javaemul.internal.annotations.DoNotInline;
import jsinterop.annotations.JsMethod;
import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsProperty;
import jsinterop.annotations.JsType;

/**
 * Tests Miscelaneous fixes.
 */
public class CompilerMiscRegressionTest extends GWTTestCase {

  @Override
  public String getModuleName() {
    return "com.google.gwt.dev.jjs.CompilerSuite";
  }

  native double toNumber(String value) /*-{
    return +value;
  }-*/;

  native double addAndConvert(double v1, String v2) /*-{
    return v1 + +v2;
  }-*/;

  native double minusAndDecrement(double val) /*-{
    var lhs = val;
    return - --lhs;
  }-*/;

  /**
   * The array {@code map.get("one")[0]} gets normalized (by {@link ImplementCastsAndTypeChecks}) to
   * {@code Cast.dynamicCast(map.get("one"), ...)[0]}. The expression resulting from dynamiCast
   * would have type Object and that would not be a valid type for an array access operation.
   */
  public void testOverridingReturnType() {
    Map<String, String[]> map = new HashMap();
    map.put("one", new String[10]);

    map.get("one")[0] = "one";
    assertEquals("one", map.get("one")[0]);
  }

  /**
   * Test for issues 6373 and 3942.
   */
  public void testUnaryPlus() {
    // With the unary + operator stripped the first assertion only fails in
    // dev mode, in web mode the  comparison made by assertEquals masks
    // the error; whereas the second fails in both dev and web modes.
    assertEquals(11.0, toNumber("11"));
    assertEquals(12.0, toNumber("10") + toNumber("2"));
    assertEquals(12.0, addAndConvert(10, "2"));
    assertEquals(-10.0, minusAndDecrement(11));
  }
  private static float[] copy(float[] src, float[] dest) {
    System.arraycopy(src, 0, dest, 0, Math.min(src.length, dest.length));
    return dest;
  }

  private void throwE(String message) {
    throw new RuntimeException(message);
  }

  /**
   * Test for issue 8243.
   */
  public void testAddAllLargeNumberOfElements() {

    int dstLength = 10;
    // Some browser have a limit on the number of parameters a function can have and 130000 barely
    // exceeds Chrome limit (as of V34).
    // This limit also applies when functions are called through apply().
    int srcLength =  130000;
    List<String> original = new ArrayList<String>();
    for (int i = 0; i < dstLength; i++) {
      original.add("foo");
    }
    List<String> src = new ArrayList<String>();
    for (int i = 0; i < srcLength; i++) {
      src.add("bar");
    }

    original.addAll(src);
    final int totalLength = srcLength + dstLength;
    assertEquals(totalLength, original.size());

    // Check the result sampling as iterating through large arrays seems costly in IE.
    for (int i = 0; i < totalLength; i += 1000) {
      if (i < dstLength) {
        assertEquals("foo", original.get(i));
      } else {
        assertEquals("bar", original.get(i));
      }
    }
  }

  /**
   * Test for issue 7253.
   */
  public void testNestedTryFollowedByTry() {
    try {
      throwE("1");
      fail("Should have thrown RuntimeException");
    } catch (RuntimeException e) {
      assertEquals("1", e.getMessage());
      try {
        throwE("2");
        fail("Should have thrown RuntimeException");
      } catch (RuntimeException e2) {
        assertEquals("2", e2.getMessage());
      }
    }
    try {
      throwE("3");
      fail("Should have thrown RuntimeException");
    } catch (RuntimeException e) {
      assertEquals("3", e.getMessage());
    }
  }

  /**
   * Test for issue 6638.
   */
  public void testNewArrayInlining() {
    float[] src = new float[]{1,1,1};
    float[] dest = copy(src, new float[3]);

    assertEqualContents(src, dest);
  }

  /**
   * Tests complex overriding patterns involving package private methods.
   * <p>
   * Test for issue 8654.
   */
  public void testOverride() {
    Caller aCaller = new Caller();
    assertEquals("SomeParentParent", aCaller.callPackagePrivatem(new SomeParentParent()));
    assertEquals("SomeParent", aCaller.callPackagePrivatem(new SomeParent()));
    assertEquals("SomeParent", aCaller.callPackagePrivatem(
        new SomeSubClassInAnotherPackage()));

    assertEquals("SomeSubClassInAnotherPackage",
        SomeSubClassInAnotherPackage.pleaseCallm(new SomeSubClassInAnotherPackage()));
    assertEquals("SomeSubSubClassInAnotherPackage",
        SomeSubClassInAnotherPackage.pleaseCallm(new SomeSubSubClassInAnotherPackage()));

    assertEquals("ClassExposingM",
        aCaller.callPackagePrivatem(new ClassExposingM()));

    SomeInterface i = new ClassExposingM();
    assertEquals("ClassExposingM", i.m());
    assertEquals("live at ClassExposingM", new ClassExposingM().f());

    // Confirm that both calling m through SomeInterface and through SomeParentParentParent
    // dispatch to the right implementation.
    SomeInterface i1 = new SubClassExposingM();
    assertEquals("SubClassExposingM", i1.m());

    assertEquals("SubClassExposingM",
        SomeParentParentParent.callSomeParentParentParentM(new SubClassExposingM()));

    assertEquals("SomeParentParentParent",
        SomeParentParentParent.callSomeParentParentParentM(new SomeParentParentParent()));
    assertEquals("SomeParentParentParent",
        SomeParentParentParent.callSomeParentParentParentM(new SomePackageConfusedParent()));
    assertEquals("SomeParentParent",
        SomeParentParentParent.callSomeParentParentParentM(new SomeParentParent()));
    assertEquals("SomeParent",
        SomeParentParentParent.callSomeParentParentParentM(new SomeParent()));
    assertEquals("SomeParent",
        SomeParentParentParent.callSomeParentParentParentM(new SomeSubClassInAnotherPackage()));
    assertEquals("SomeParent",
        SomeParentParentParent.callSomeParentParentParentM(new SomeSubSubClassInAnotherPackage()));
  }

  enum MyEnum {
    A,
    B,
    C;

    public final static MyEnum[] VALUES = values();

    public int getPriority() {
      return VALUES.length - ordinal();
    }
  }

  /**
   * Tests that enum ordinalizer does not incorrectly optimize {@code MyEnum}.
   * <p>
   * Test for issue 8846.
   */
  public void testMyEnum() {
    assertEquals(2, MyEnum.B.getPriority());
  }

  enum OrderingProblem {
    A,
    B;

    public static OrderingProblem getPriority1() {
      if (new Integer(1).toString().isEmpty()) {
        return B;
      }
      return A;
    }
  }

  /**
   * Test for regression introduced in patch https://gwt-review.googlesource.com/#/c/9083; where
   * depending on the order in which references to the enum class were encountered, some instances
   * were not correctly replaced .
   */
  public void testOrderingProblem() {
    assertEquals(OrderingProblem.A.ordinal(), OrderingProblem.getPriority1().ordinal());
  }

  /**
   * Tests that regexes are not incorrectly internalized.
   *
   * Test for issue 8865.
   */
  public native void testJavaScriptRegExps() /*-{
    // Make regexes large enough so that the will be interned (if regex interning was enabled).
    var regExp1 = /this is a string where the search/g;
    var regExp2 = /this is a string where the search/g;
    var str = "this is a string where the search occurs";
    @junit.framework.Assert::assertEquals(ZZ)(
       regExp1.test(str), regExp2.test(str));
  }-*/;

  private static final double MINUTES_IN_DAY = 24 * 60;

  @DoNotInline
  public void assertStaticEvaluationRegression(int hour, int minute) {
    // Do not inline this method so that the problematic expression reaches JsStaticEval.
    double expected = hour * 60 + minute;
    expected /= MINUTES_IN_DAY;
    expected *= 100;
    assertEquals(expected , (hour * 60 + minute) / MINUTES_IN_DAY * 100);
  }

  /**
   * Test for issue 8934.
   */
  public void testStaticEvaluationRegression() {
    // Perform two calls with different constant values to make sure the assertStaticEvaluation does
    // not get the constant parameters propagated and statically evaluated in the Java AST.
    assertStaticEvaluationRegression(10, 20);
    assertStaticEvaluationRegression(20, 10);
  }

  /**
   * Test for issue 8909.
   * <p>
   * DevMode does not conform to JS arithmetic semantics and this method tests exactly that.
   */
  @DoNotRunWith(Platform.Devel)
  public void testStaticEvaluationSematics() {
    float num = getRoundedValue(1.005f);
    assertEquals(1.00, num, 0.001);
  }

  private float getRoundedValue(float parameter) {
    float local = parameter;
    local = local * 100f;
    return Math.round(local) / 100f;
  }

  /**
   * Test for issue 9043.
   */
  public native void testMultipleClassLiteralReferences() /*-{
    var a = @com.google.gwt.dev.jjs.test.CompilerMiscRegressionTest::class;
    var b = @com.google.gwt.dev.jjs.test.CompilerMiscRegressionTest::class;
  }-*/;

  /**
   * Test for issue 9153.
   * <p>
   * Typetightener used to incorrectly tighten method calls marked with STATIC_DISPATCH_ONLY.
   */

  public void testIncorrectDispatch() {
    state = new int[1];
    new B().m();
    assertEquals(1, state[0]);
  }

  static int[] state;
  @JsType
  abstract static class A {
    public void m() {
      state[0] = 1;
    }
  }

  @JsType
  static class B extends A {
    public void m() {
      super.m();
    }
  }

  private static void assertEqualContents(float[] expected, float[] actual) {

    assertEquals("Array length mismatch", expected.length, actual.length);
    for (int i = 0; i < expected.length; i++) {
      assertEquals("Array mismatch at element " + i , expected[i], actual[i]);
    }
  }

  @JsType(isNative = true)
  interface SomeNativeInterface {
    @JsProperty
    String getTextContent();
  }

  @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
  static abstract class AbstractNativeType implements SomeNativeInterface {
  }

  private static native AbstractNativeType createAbstractNativeType(String value) /*-{
    return {textContent : value};
  }-*/;

  // Tests that methods that override native JsMethods are generated properly w.r.t
  // JsMethod/JsProperty annotations even if the overridden method is not live.
  // See bug #9358
  //
  // Make sure this method is part of a suite that is run with -nogenerateJsInteropExports.
  public void testNativeJsMethodDispatch_unreferencedSupertypeMethod() {
    final AbstractNativeType o = createAbstractNativeType("Hello");
    assertEquals("Hello", o.getTextContent());
  }

  @JsMethod
  private static List<String> singletonFrom(int i, String... arguments) {
    // Make the second parameter varargs and pass it as a whole to trigger the arguments copying
    // preamble.
    return Arrays.asList(arguments).subList(i,i + 1);
  }

  @JsMethod
  private static List<String> argumentsParameterClasher(int arguments, String... others) {
    // Make the second parameter varargs and pass it as a whole to trigger the arguments copying
    // preamble.
    return Arrays.asList(others).subList(0, arguments);
  }

  @JsMethod
  private static List<String> argumentsVariableClasher(int i, String... others) {
    // Make the second parameter varargs and pass it as a whole to trigger the arguments copying
    // preamble.
    {
      int arguments = 3;
    }
    return Arrays.asList(others).subList(0, i);
  }

 public void testVarargsNamedArguments() {
    assertEquals("GoodBye", singletonFrom(1, "Hello", "GoodBye").get(0));
    assertEquals("Hello", argumentsParameterClasher(1, "Hello", "GoodBye").get(0));
    assertEquals("Hello", argumentsVariableClasher(1, "Hello", "GoodBye").get(0));
  }

  @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Array")
  private static class NativeArray {
    @JsProperty(name = "length")
    public int len;
    @JsMethod(name = "push")
    public native void add(double element);
  }

  private static native Object newArray() /*-{
    return @NativeArray::new()();
  }-*/;

  private static native int arrayLength(Object array) /*-{
    return array.@NativeArray::len;
  }-*/;

  private static native void arrayAdd(Object array, double d) /*-{
    array.@NativeArray::add(D)(d);
    return array;
  }-*/;

  private static native Object newArrayThroughCtorReference() /*-{
    var ctor =  @NativeArray::new();
    return ctor();
  }-*/;

  private static native boolean isNan(double number) /*-{
    return @Global::isNan(D)(number);
  }-*/;

  private static native double getNan() /*-{
    return @Global::Nan;
  }-*/;

  @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
  private static class Global {
    @JsProperty(namespace = JsPackage.GLOBAL, name = "NaN")
    public static double Nan;
    @JsMethod(namespace = JsPackage.GLOBAL, name = "isNaN")
    public static native boolean isNan(double number);
  }

  // Regression tests for issue #9520.
  public void testNativeConstructorJSNI() {
    Object nativeArray = newArray();
    arrayAdd(nativeArray, 0);
    arrayAdd(nativeArray, 1);
    assertTrue(nativeArray instanceof NativeArray);
    assertEquals(2, arrayLength(nativeArray));
    assertTrue(newArrayThroughCtorReference() instanceof NativeArray);
    assertTrue(Double.isNaN(getNan()));
    assertTrue(isNan(Double.NaN));
  }
}
