/*
 * Copyright 2010 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.web.bindery.autobean.shared;

import com.google.web.bindery.autobean.shared.AutoBean.PropertyName;
import com.google.web.bindery.autobean.shared.impl.EnumMap;
import com.google.gwt.core.client.GWT;
import com.google.gwt.junit.client.GWTTestCase;

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

/**
 * Simple encoding / decoding tests for the AutoBeanCodex.
 */
public class AutoBeanCodexTest extends GWTTestCase {
  /**
   * Protected so that the JRE-only test can instantiate instances.
   */
  protected interface Factory extends AutoBeanFactory {
    AutoBean<HasSplittable> hasAutoBean();

    AutoBean<HasCycle> hasCycle();

    AutoBean<HasEnum> hasEnum();

    AutoBean<HasList> hasList();

    AutoBean<HasMap> hasMap();

    AutoBean<HasSimple> hasSimple();

    AutoBean<Simple> simple();
  }

  /*
   * These enums are used to verify that a List<Enum> or Map<Enum, Enum> pulls
   * in the necessary metadata.
   */
  enum EnumReachableThroughList {
    FOO_LIST
  }

  enum EnumReachableThroughMapKey {
    FOO_KEY
  }

  enum EnumReachableThroughMapValue {
    FOO_VALUE
  }

  /**
   * Used to test that cycles are detected.
   */
  interface HasCycle {
    List<HasCycle> getCycle();

    void setCycle(List<HasCycle> cycle);
  }

  interface HasEnum {
    MyEnum getEnum();

    List<MyEnum> getEnums();

    Map<MyEnum, Integer> getMap();

    List<EnumReachableThroughList> getParameterizedList();

    Map<EnumReachableThroughMapKey, EnumReachableThroughMapValue> getParameterizedMap();

    void setEnum(MyEnum value);

    void setEnums(List<MyEnum> value);

    void setMap(Map<MyEnum, Integer> value);
  }

  interface HasList {
    List<Integer> getIntList();

    List<Simple> getList();

    void setIntList(List<Integer> list);

    void setList(List<Simple> list);
  }

  interface HasMap {
    Map<Simple, Simple> getComplexMap();

    Map<Map<String, String>, Map<String, String>> getNestedMap();

    Map<String, Simple> getSimpleMap();

    void setComplexMap(Map<Simple, Simple> map);

    void setNestedMap(Map<Map<String, String>, Map<String, String>> map);

    void setSimpleMap(Map<String, Simple> map);
  }

  interface HasSimple {
    Simple getSimple();

    void setSimple(Simple s);
  }

  interface HasSplittable {
    Splittable getSimple();

    List<Splittable> getSimpleList();

    Map<Splittable, Splittable> getSplittableMap();

    Splittable getString();

    void setSimple(Splittable simple);

    void setSimpleList(List<Splittable> simple);

    void setSplittableMap(Map<Splittable, Splittable> map);

    void setString(Splittable s);
  }

  enum MyEnum {
    FOO, BAR,
    // The eclipse formatter wants to put this annotation inline
    @PropertyName("quux")
    BAZ;
  }

  interface ReachableOnlyFromParameterization extends Simple {
  }

  interface Simple {
    int getInt();

    String getString();

    Boolean hasOtherBoolean();

    boolean isBoolean();

    void setBoolean(boolean b);

    void setInt(int i);

    void setOtherBoolean(Boolean b);

    void setString(String s);
  }

  protected Factory f;

  @Override
  public String getModuleName() {
    return "com.google.web.bindery.autobean.AutoBean";
  }

  public void testCycle() {
    AutoBean<HasCycle> bean = f.hasCycle();
    bean.as().setCycle(Arrays.asList(bean.as()));
    try {
      checkEncode(bean);
      fail("Should not have encoded");
    } catch (UnsupportedOperationException expected) {
    }
  }

  public void testEmptyList() {
    AutoBean<HasList> bean = f.hasList();
    bean.as().setList(Collections.<Simple> emptyList());
    AutoBean<HasList> decodedBean = checkEncode(bean);
    assertNotNull(decodedBean.as().getList());
    assertTrue(decodedBean.as().getList().isEmpty());
  }

  public void testEnum() {
    EnumMap map = (EnumMap) f;
    assertEquals("BAR", map.getToken(MyEnum.BAR));
    assertEquals("quux", map.getToken(MyEnum.BAZ));
    assertEquals(MyEnum.BAR, map.getEnum(MyEnum.class, "BAR"));
    assertEquals(MyEnum.BAZ, map.getEnum(MyEnum.class, "quux"));

    List<MyEnum> arrayValue = Arrays.asList(MyEnum.FOO, MyEnum.BAR, null, MyEnum.BAZ);
    Map<MyEnum, Integer> mapValue = new HashMap<MyEnum, Integer>();
    mapValue.put(MyEnum.FOO, 0);
    mapValue.put(MyEnum.BAR, 1);
    mapValue.put(MyEnum.BAZ, 2);

    AutoBean<HasEnum> bean = f.hasEnum();
    bean.as().setEnum(MyEnum.BAZ);
    bean.as().setEnums(arrayValue);
    bean.as().setMap(mapValue);

    Splittable split = AutoBeanCodex.encode(bean);
    // Make sure the overridden form is always used
    assertFalse(split.getPayload().contains("BAZ"));

    AutoBean<HasEnum> decoded = checkEncode(bean);
    assertEquals(MyEnum.BAZ, decoded.as().getEnum());
    assertEquals(arrayValue, decoded.as().getEnums());
    assertEquals(mapValue, decoded.as().getMap());

    assertEquals(MyEnum.BAZ, AutoBeanUtils.getAllProperties(bean).get("enum"));
    bean.as().setEnum(null);
    assertNull(bean.as().getEnum());
    assertNull(AutoBeanUtils.getAllProperties(bean).get("enum"));
    decoded = checkEncode(bean);
    assertNull(decoded.as().getEnum());
  }

  /**
   * Ensures that enum types that are reachable only through a method
   * parameterization are included in the enum map.
   */
  public void testEnumReachableOnlyThroughParameterization() {
    EnumMap map = (EnumMap) f;
    assertEquals("FOO_LIST", map.getToken(EnumReachableThroughList.FOO_LIST));
    assertEquals("FOO_KEY", map.getToken(EnumReachableThroughMapKey.FOO_KEY));
    assertEquals("FOO_VALUE", map.getToken(EnumReachableThroughMapValue.FOO_VALUE));
    assertEquals(EnumReachableThroughList.FOO_LIST, map.getEnum(EnumReachableThroughList.class,
        "FOO_LIST"));
    assertEquals(EnumReachableThroughMapKey.FOO_KEY, map.getEnum(EnumReachableThroughMapKey.class,
        "FOO_KEY"));
    assertEquals(EnumReachableThroughMapValue.FOO_VALUE, map.getEnum(
        EnumReachableThroughMapValue.class, "FOO_VALUE"));
  }

  public void testMap() {
    AutoBean<HasMap> bean = f.hasMap();
    Map<String, Simple> map = new HashMap<String, Simple>();
    Map<Simple, Simple> complex = new HashMap<Simple, Simple>();
    bean.as().setSimpleMap(map);
    bean.as().setComplexMap(complex);

    for (int i = 0, j = 5; i < j; i++) {
      Simple s = f.simple().as();
      s.setInt(i);
      map.put(String.valueOf(i), s);

      Simple key = f.simple().as();
      key.setString(String.valueOf(i));
      complex.put(key, s);
    }

    AutoBean<HasMap> decoded = checkEncode(bean);
    map = decoded.as().getSimpleMap();
    complex = decoded.as().getComplexMap();
    assertEquals(5, map.size());
    for (int i = 0, j = 5; i < j; i++) {
      Simple s = map.get(String.valueOf(i));
      assertNotNull(s);
      assertEquals(i, s.getInt());
    }
    assertEquals(5, complex.size());
    for (Map.Entry<Simple, Simple> entry : complex.entrySet()) {
      assertEquals(entry.getKey().getString(), String.valueOf(entry.getValue().getInt()));
    }
  }

  /**
   * Verify that arbitrarily complicated Maps of Maps work.
   */
  public void testNestedMap() {
    Map<String, String> key = new HashMap<String, String>();
    key.put("a", "b");

    Map<String, String> value = new HashMap<String, String>();
    value.put("c", "d");

    Map<Map<String, String>, Map<String, String>> test =
        new HashMap<Map<String, String>, Map<String, String>>();
    test.put(key, value);

    AutoBean<HasMap> bean = f.hasMap();
    bean.as().setNestedMap(test);

    AutoBean<HasMap> decoded = checkEncode(bean);
    assertEquals(1, decoded.as().getNestedMap().size());
  }

  public void testNull() {
    AutoBean<Simple> bean = f.simple();
    AutoBean<Simple> decodedBean = checkEncode(bean);
    assertNull(decodedBean.as().getString());
  }

  public void testSimple() {
    AutoBean<Simple> bean = f.simple();
    Simple simple = bean.as();
    simple.setBoolean(true);
    simple.setInt(42);
    simple.setOtherBoolean(true);
    simple.setString("Hello World!");

    AutoBean<Simple> decodedBean = checkEncode(bean);
    assertTrue(AutoBeanUtils.diff(bean, decodedBean).isEmpty());
    assertTrue(decodedBean.as().isBoolean());
    assertTrue(decodedBean.as().hasOtherBoolean());

    AutoBean<HasSimple> bean2 = f.hasSimple();
    bean2.as().setSimple(simple);

    AutoBean<HasSimple> decodedBean2 = checkEncode(bean2);
    assertNotNull(decodedBean2.as().getSimple());
    assertTrue(AutoBeanUtils.diff(bean, AutoBeanUtils.getAutoBean(decodedBean2.as().getSimple()))
        .isEmpty());

    AutoBean<HasList> bean3 = f.hasList();
    bean3.as().setIntList(Arrays.asList(1, 2, 3, null, 4, 5));
    bean3.as().setList(Arrays.asList(simple));

    AutoBean<HasList> decodedBean3 = checkEncode(bean3);
    assertNotNull(decodedBean3.as().getIntList());
    assertEquals(Arrays.asList(1, 2, 3, null, 4, 5), decodedBean3.as().getIntList());
    assertNotNull(decodedBean3.as().getList());
    assertEquals(1, decodedBean3.as().getList().size());
    assertTrue(AutoBeanUtils.diff(bean,
        AutoBeanUtils.getAutoBean(decodedBean3.as().getList().get(0))).isEmpty());
  }

  public void testSplittable() {
    AutoBean<Simple> simple = f.simple();
    simple.as().setString("Simple");
    AutoBean<HasSplittable> bean = f.hasAutoBean();
    bean.as().setSimple(AutoBeanCodex.encode(simple));
    bean.as().setString(ValueCodex.encode("Hello ['\"] world"));
    List<Splittable> testList =
        Arrays.asList(AutoBeanCodex.encode(simple), null, AutoBeanCodex.encode(simple));
    bean.as().setSimpleList(testList);
    Map<Splittable, Splittable> testMap =
        Collections.singletonMap(ValueCodex.encode("12345"), ValueCodex.encode("5678"));
    bean.as().setSplittableMap(testMap);

    AutoBean<HasSplittable> decoded = checkEncode(bean);
    Splittable toDecode = decoded.as().getSimple();
    AutoBean<Simple> decodedSimple = AutoBeanCodex.decode(f, Simple.class, toDecode);
    assertEquals("Simple", decodedSimple.as().getString());
    assertEquals("Hello ['\"] world", ValueCodex.decode(String.class, decoded.as().getString()));
    assertEquals("12345", decoded.as().getSplittableMap().keySet().iterator().next().asString());
    assertEquals("5678", decoded.as().getSplittableMap().values().iterator().next().asString());

    List<Splittable> list = decoded.as().getSimpleList();
    assertEquals(3, list.size());
    assertNull(list.get(1));
    assertEquals("Simple", AutoBeanCodex.decode(f, Simple.class, list.get(2)).as().getString());
  }

  @Override
  protected void gwtSetUp() throws Exception {
    f = GWT.create(Factory.class);
  }

  private <T> AutoBean<T> checkEncode(AutoBean<T> bean) {
    Splittable split = AutoBeanCodex.encode(bean);
    AutoBean<T> decoded = AutoBeanCodex.decode(f, bean.getType(), split);
    assertTrue(AutoBeanUtils.deepEquals(bean, decoded));
    return decoded;
  }
}
