/*
 * 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.gwt.autobean.shared;

import com.google.gwt.autobean.shared.AutoBean.PropertyName;
import com.google.gwt.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<HasAutoBean> 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
  }

  interface HasAutoBean {
    Splittable getSimple();

    List<Splittable> getSimpleList();

    Splittable getString();

    void setSimple(Splittable simple);

    void setSimpleList(List<Splittable> simple);

    void setString(Splittable s);
  }

  /**
   * 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<String, Simple> getSimpleMap();

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

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

  interface HasSimple {
    Simple getSimple();

    void setSimple(Simple 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();

    void setInt(int i);

    void setString(String s);
  }

  protected Factory f;

  @Override
  public String getModuleName() {
    return "com.google.gwt.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, 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());
  }

  /**
   * 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()));
    }
  }

  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.setInt(42);
    simple.setString("Hello World!");

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

    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<HasAutoBean> 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);

    AutoBean<HasAutoBean> 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()));

    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;
  }
}
