/*
 * Copyright 2015 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.core.interop;

import static jsinterop.annotations.JsPackage.GLOBAL;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.ScriptInjector;
import com.google.gwt.junit.client.GWTTestCase;

import jsinterop.annotations.JsProperty;
import jsinterop.annotations.JsType;

/**
 * Tests JsProperty functionality.
 */
public class JsPropertyTest extends GWTTestCase {

  private static final int SET_PARENT_X = 500;
  private static final int GET_PARENT_X = 1000;
  private static final int GET_X = 100;
  private static final int SET_X = 50;

  @Override
  public String getModuleName() {
    return "com.google.gwt.core.Interop";
  }

  @Override
  protected void gwtSetUp() throws Exception {
    ScriptInjector.fromString(
        "function JsPropertyTest_MyNativeJsType(x) { this.x = x; this.ctorExecuted = true; }\n"
        + "JsPropertyTest_MyNativeJsType.staticX = 33;"
        + "JsPropertyTest_MyNativeJsType.answerToLife = function() { return 42;};"
        + "JsPropertyTest_MyNativeJsType.prototype.sum = "
        + "    function sum(bias) { return this.x + bias; };"
        + "function JsPropertyTest_MyNativeJsTypeInterface() {}\n"
        + "JsPropertyTest_MyNativeJsTypeInterface.prototype.sum = "
        + "    function sum(bias) { return this.x + bias; };")
        .setWindow(ScriptInjector.TOP_WINDOW).inject();
  }

  @JsType
  interface MyJsTypeInterfaceWithProperty {
    @JsProperty
    int getX();

    @JsProperty
    void setX(int x);
  }

  static class MyJavaTypeImplementingMyJsTypeInterfaceWithProperty
      implements MyJsTypeInterfaceWithProperty {
    private int x;

    public int getX() {
      return x + GET_X;
    }

    public void setX(int x) {
      this.x = x + SET_X;
    }
  }

  public void testJavaClassImplementingMyJsTypeInterfaceWithProperty() {
    MyJavaTypeImplementingMyJsTypeInterfaceWithProperty obj =
        new MyJavaTypeImplementingMyJsTypeInterfaceWithProperty();
    assertEquals(0 + GET_X, getProperty(obj, "x"));
    assertEquals(0 + GET_X, obj.getX());
    assertEquals(0, obj.x);

    setProperty(obj, "x", 10);
    assertEquals(10 + GET_X + SET_X, getProperty(obj, "x"));
    assertEquals(10 + GET_X + SET_X, obj.getX());
    assertEquals(10 + SET_X, obj.x);

    obj.setX(12);
    assertEquals(12 + GET_X + SET_X, getProperty(obj, "x"));
    assertEquals(12 + GET_X + SET_X, obj.getX());
    assertEquals(12 + SET_X, obj.x);

    MyJsTypeInterfaceWithProperty intf = new MyJavaTypeImplementingMyJsTypeInterfaceWithProperty();
    assertEquals(0 + GET_X, getProperty(intf, "x"));
    assertEquals(0 + GET_X, intf.getX());
    assertEquals(0, ((MyJavaTypeImplementingMyJsTypeInterfaceWithProperty) intf).x);

    setProperty(intf, "x", 10);
    assertEquals(10 + GET_X + SET_X, getProperty(intf, "x"));
    assertEquals(10 + GET_X + SET_X, intf.getX());
    assertEquals(10 + SET_X, ((MyJavaTypeImplementingMyJsTypeInterfaceWithProperty) intf).x);

    intf.setX(12);
    assertEquals(12 + GET_X + SET_X, getProperty(intf, "x"));
    assertEquals(12 + GET_X + SET_X, intf.getX());
    assertEquals(12 + SET_X, ((MyJavaTypeImplementingMyJsTypeInterfaceWithProperty) intf).x);
  }

  @JsType
  static class MyConcreteJsType {
    private int x;

    @JsProperty
    public int getY() {
      return x + GET_X;
    }

    @JsProperty
    public void setY(int x) {
      this.x = x + SET_X;
    }
  }

  public void testConcreteJsType() {
    MyConcreteJsType obj = new MyConcreteJsType();
    assertEquals(0 + GET_X, getProperty(obj, "y"));
    assertEquals(0 + GET_X,obj.getY());
    assertEquals(0, obj.x);

    setProperty(obj, "y", 10);
    assertEquals(10 + GET_X + SET_X, getProperty(obj, "y"));
    assertEquals(10 + GET_X + SET_X, obj.getY());
    assertEquals(10 + SET_X, obj.x);

    obj.setY(12);
    assertEquals(12 + GET_X + SET_X, getProperty(obj, "y"));
    assertEquals(12 + GET_X + SET_X, obj.getY());
    assertEquals(12 + SET_X, obj.x);
  }

  @JsType(isNative = true, namespace = GLOBAL, name = "JsPropertyTest_MyNativeJsType")
  static class MyNativeJsType {

    public static int staticX;

    public static native int answerToLife();

    public boolean ctorExecuted;

    public int x;

    @JsProperty
    public native int getY();

    @JsProperty
    public native void setY(int x);

    public native int sum(int bias);
  }

  public void testNativeJsType() {
    assertEquals(33, MyNativeJsType.staticX);
    MyNativeJsType.staticX = 34;
    assertEquals(34, MyNativeJsType.staticX);
    assertEquals(42, MyNativeJsType.answerToLife());

    MyNativeJsType obj = new MyNativeJsType();
    assertTrue(obj.ctorExecuted);
    assertTrue(isUndefined(obj.x));
    obj.x = 72;
    assertEquals(72, obj.x);
    assertEquals(74, obj.sum(2));

    assertTrue(isUndefined(obj.getY()));
    obj.setY(91);
    assertEquals(91, obj.getY());
  }

  static class MyNativeJsTypeSubclass extends MyNativeJsType {

    MyNativeJsTypeSubclass() {
      this.x = 42;
      setY(52);
    }

    @Override
    public int sum(int bias) {
      return super.sum(bias) + GET_X;
    }
  }

  public void testNativeJsTypeSubclass() {
    MyNativeJsTypeSubclass mc = new MyNativeJsTypeSubclass();
    assertTrue(mc.ctorExecuted);
    assertEquals(143, mc.sum(1));

    mc.x = -mc.x;
    assertEquals(58, mc.sum(0));

    assertEquals(52, mc.getY());
  }

  static class MyNativeJsTypeSubclassNoOverride extends MyNativeJsType { }

  // TODO(rluble): enable when the subclass is setup correctly.
  public void _disabled_testNativeJsTypeSubclassNoOverride() {
    MyNativeJsTypeSubclassNoOverride myNativeJsType = new MyNativeJsTypeSubclassNoOverride();
    myNativeJsType.x = 12;
    assertEquals(42, myNativeJsType.sum(30));
  }

  @JsType(isNative = true, namespace = GLOBAL, name = "JsPropertyTest_MyNativeJsType")
  static class MyNativeJsTypeWithConstructor {
    public MyNativeJsTypeWithConstructor(int x) { }
    public boolean ctorExecuted;
    public int x;
  }

  public void testNativeJsTypeWithConstructor() {
    MyNativeJsTypeWithConstructor obj = new MyNativeJsTypeWithConstructor(12);
    assertTrue(obj.ctorExecuted);
    assertEquals(12, obj.x);
  }

  static class MyNativeJsTypeWithConstructorSubclass extends MyNativeJsTypeWithConstructor {
    public MyNativeJsTypeWithConstructorSubclass(int x) {
      super(x);
    }
  }

  public void testNativeJsTypeWithConstructorSubclass() {
    MyNativeJsTypeWithConstructorSubclass obj = new MyNativeJsTypeWithConstructorSubclass(12);
    assertTrue(obj.ctorExecuted);
    assertEquals(12, obj.x);
  }

  @JsType(isNative = true, namespace = GLOBAL, name = "JsPropertyTest_MyNativeJsTypeInterface")
  interface MyNativeJsTypeInterface {
    @JsProperty
    int getX();

    @JsProperty
    void setX(int x);
  }

  static class MyNativeJsTypeInterfaceImplementorNeedingBridge
      extends AccidentalImplementer implements MyNativeJsTypeInterface {
  }

  static abstract class AccidentalImplementer {
    private int x;

    public int getX() {
      return x + GET_X;
    }

    public void setX(int x) {
      this.x = x + SET_X;
    }

    public int sum(int bias) {
      return bias + x;
    }
  }

  public void testJsPropertyBridges() {
    MyNativeJsTypeInterface object = new MyNativeJsTypeInterfaceImplementorNeedingBridge();

    object.setX(3);
    assertEquals(3 + 150, object.getX());
    assertEquals(3 + SET_X, ((AccidentalImplementer) object).x);

    AccidentalImplementer accidentalImplementer = (AccidentalImplementer) object;

    accidentalImplementer.setX(3);
    assertEquals(3 + 150, accidentalImplementer.getX());
    assertEquals(3 + 150, getProperty(object, "x"));
    assertEquals(3 + SET_X, accidentalImplementer.x);

    setProperty(object, "x", 4);
    assertEquals(4 + 150, accidentalImplementer.getX());
    assertEquals(4 + 150, getProperty(object, "x"));
    assertEquals(4 + SET_X, accidentalImplementer.x);

    assertEquals(3 + 4 + SET_X, accidentalImplementer.sum(3));
  }

  static class MyNativeJsTypeInterfaceImplNeedingBridgeSubclassed
      extends OtherAccidentalImplementer implements MyNativeJsTypeInterface {
  }

  static abstract class OtherAccidentalImplementer {
    private int x;

    public int getX() {
      return x + GET_PARENT_X;
    }

    public void setX(int x) {
      this.x = x + SET_PARENT_X;
    }

    public int sum(int bias) {
      return bias + x;
    }
  }

  static class MyNativeJsTypeInterfaceImplNeedingBridgeSubclass
      extends MyNativeJsTypeInterfaceImplNeedingBridgeSubclassed {
    private int y;

    public int getX() {
      return y + GET_X;
    }

    public void setX(int y) {
      this.y = y + SET_X;
    }

    public void setParentX(int value) {
      super.setX(value);
    }

    public int getXPlusY() {
      return super.getX() + y;
    }
  }

  public void testJsPropertyBridgesSubclass() {
    MyNativeJsTypeInterface object = new MyNativeJsTypeInterfaceImplNeedingBridgeSubclass();

    object.setX(3);
    assertEquals(3 + 150, object.getX());

    OtherAccidentalImplementer simple = (OtherAccidentalImplementer) object;

    simple.setX(3);
    assertEquals(3 + GET_X + SET_X, simple.getX());
    assertEquals(3 + GET_X + SET_X, getProperty(object, "x"));
    assertEquals(3 + SET_X, ((MyNativeJsTypeInterfaceImplNeedingBridgeSubclass) object).y);
    assertEquals(0, ((OtherAccidentalImplementer) object).x);

    setProperty(object, "x", 4);
    assertEquals(4 + GET_X + SET_X, simple.getX());
    assertEquals(4 + GET_X + SET_X, getProperty(object, "x"));
    assertEquals(4 + SET_X, ((MyNativeJsTypeInterfaceImplNeedingBridgeSubclass) object).y);
    assertEquals(0, ((OtherAccidentalImplementer) object).x);

    MyNativeJsTypeInterfaceImplNeedingBridgeSubclass subclass =
        (MyNativeJsTypeInterfaceImplNeedingBridgeSubclass) object;

    subclass.setParentX(5);
    assertEquals(8 + SET_PARENT_X, simple.sum(3));
    assertEquals(9 + SET_PARENT_X + GET_PARENT_X + SET_X, subclass.getXPlusY());
    assertEquals(4 + SET_X, ((MyNativeJsTypeInterfaceImplNeedingBridgeSubclass) object).y);
    assertEquals(5 + SET_PARENT_X, ((OtherAccidentalImplementer) object).x);
  }

  @JsType(isNative = true)
  interface MyJsTypeInterfaceWithProtectedNames {
    String var();

    @JsProperty
    String getNullField(); // Defined in object scope but shouldn't obfuscate

    @JsProperty
    String getImport();

    @JsProperty
    void setImport(String str);
  }

  public void testProtectedNames() {
    MyJsTypeInterfaceWithProtectedNames obj = createMyJsInterfaceWithProtectedNames();
    assertEquals("var", obj.var());
    assertEquals("nullField", obj.getNullField());
    assertEquals("import", obj.getImport());
    obj.setImport("import2");
    assertEquals("import2", obj.getImport());
  }

  @JsType(isNative = true)
  interface JsTypeIsProperty {

    @JsProperty
    boolean isX();

    @JsProperty
    void setX(boolean x);
  }

  public void testJsPropertyIsX() {
    JsTypeIsProperty object = (JsTypeIsProperty) JavaScriptObject.createObject();

    assertFalse(object.isX());
    object.setX(true);
    assertTrue(object.isX());
    object.setX(false);
    assertFalse(object.isX());
  }

  @JsType(isNative = true)
  interface AccidentalOverridePropertyJsTypeInterface {
    @JsProperty
    int getX();
  }

  static class AccidentalOverridePropertyBase {
    public int getX() {
      return 50;
    }
  }

  static class AccidentalOverrideProperty extends AccidentalOverridePropertyBase
      implements AccidentalOverridePropertyJsTypeInterface {
  }

  public void testJsPropertyAccidentalOverrideSuperCall() {
    AccidentalOverrideProperty object = new AccidentalOverrideProperty();
    assertEquals(50, object.getX());
    assertEquals(50, getProperty(object, "x"));
  }

  @JsType
  static class RemovedAccidentalOverridePropertyBase {
    @JsProperty
    public int getX() {
      return 55;
    }
  }

  static class RemovedAccidentalOverrideProperty extends RemovedAccidentalOverridePropertyBase
      implements AccidentalOverridePropertyJsTypeInterface {
  }

  public void testJsPropertyRemovedAccidentalOverrideSuperCall() {
    RemovedAccidentalOverrideProperty object = new RemovedAccidentalOverrideProperty();
    // If the accidental override here were not removed the access to property x would result in
    // an infinite loop
    assertEquals(55, object.getX());
    assertEquals(55, getProperty(object, "x"));
  }

  @JsType(isNative = true)
  interface JsTypeGetProperty {

    @JsProperty
    int getX();

    @JsProperty
    void setX(int x);
  }

  public void testJsPropertyGetX() {
    JsTypeGetProperty object = (JsTypeGetProperty) JavaScriptObject.createObject();

    assertTrue(isUndefined(object.getX()));
    object.setX(10);
    assertEquals(10, object.getX());
    object.setX(0);
    assertEquals(0, object.getX());
  }

  private static native MyJsTypeInterfaceWithProtectedNames createMyJsInterfaceWithProtectedNames() /*-{
    var a = {};
    a["nullField"] = "nullField";
    a["import"] = "import";
    a["var"] = function() { return "var"; };
    return a;
  }-*/;

  private static native boolean isUndefined(int value) /*-{
    return value === undefined;
  }-*/;

  private static native boolean hasField(Object object, String fieldName) /*-{
    return object[fieldName] != undefined;
  }-*/;

  private static native int getProperty(Object object, String name) /*-{
    return object[name];
  }-*/;

  private static native void setProperty(Object object, String name, int value) /*-{
    object[name] = value;
  }-*/;

  public static void assertJsTypeHasFields(Object obj, String... fields) {
    for (String field : fields) {
      assertTrue("Field '" + field + "' should be exported", hasField(obj, field));
    }
  }

  public static void assertJsTypeDoesntHaveFields(Object obj, String... fields) {
    for (String field : fields) {
      assertFalse("Field '" + field + "' should not be exported", hasField(obj, field));
    }
  }

  static class B {
    @JsProperty
    public String field;
  }

  private native String getB(B b) /*-{
    return b.field;
  }-*/;

  public void testNotReadExportedFieldNotPruned() {
    B b = new B();
    b.field = "secret";
    assertEquals("secret", getB(b));
  }

  @JsType
  static class ClassWithFieldNotWrittenInJava {
    public int fieldNotWrittenInJava = 0;
  }

  private native String setFieldNotWrittenInJava(Object obj, int value) /*-{
    obj.fieldNotWrittenInJava = value;
  }-*/;

  public void testFieldNotWrittenInJava() {
    ClassWithFieldNotWrittenInJava obj = new ClassWithFieldNotWrittenInJava();
    assertEquals(0, obj.fieldNotWrittenInJava);
    setFieldNotWrittenInJava(obj, 2);
    assertEquals(2, obj.fieldNotWrittenInJava);
  }
}
