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

import com.google.gwt.core.client.GWT;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.web.bindery.autobean.shared.AutoBean;
import com.google.web.bindery.autobean.shared.AutoBeanFactory;
import com.google.web.bindery.autobean.shared.AutoBeanFactory.Category;
import com.google.web.bindery.autobean.shared.AutoBeanUtils;
import com.google.web.bindery.autobean.shared.AutoBeanVisitor;
import com.google.web.bindery.autobean.shared.AutoBeanVisitor.ParameterizationVisitor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/**
 * Tests runtime behavior of AutoBean framework.
 */
public class AutoBeanTest extends GWTTestCase {

  /**
   * Static implementation of {@link HasCall}.
   */
  public static class CallImpl {
    public static Object seen;

    public static <T> T __intercept(AutoBean<HasCall> bean, T value) {
      assertNotNull(bean);
      seen = value;
      return value;
    }

    public static int add(AutoBean<HasCall> bean, int a, int b) {
      assertNotNull(bean);
      return ((Integer) bean.getTag("offset")) + a + b;
    }
  }

  /**
   * The factory being tested.
   */
  @Category(CallImpl.class)
  protected interface Factory extends AutoBeanFactory {
    AutoBean<HasBoolean> hasBoolean();

    AutoBean<HasCall> hasCall();

    AutoBean<HasChainedSetters> hasChainedSetters();

    AutoBean<HasList> hasList();

    AutoBean<HasComplexTypes> hasListOfList();

    AutoBean<HasMoreChainedSetters> hasMoreChainedSetters();

    AutoBean<Intf> intf();

    AutoBean<Intf> intf(RealIntf wrapped);

    AutoBean<OtherIntf> otherIntf();
  }

  interface HasBoolean {
    boolean getGet();

    boolean hasHas();

    boolean isIs();

    void setGet(boolean value);

    void setHas(boolean value);

    void setIs(boolean value);
  }

  interface HasCall {
    int add(int a, int b);
  }

  interface HasChainedSetters {
    int getInt();

    String getString();

    HasChainedSetters setInt(int value);

    HasChainedSetters setString(String value);
  }

  interface HasComplexTypes {
    List<List<Intf>> getList();

    List<Map<String, Intf>> getListOfMap();

    Map<Map<String, String>, List<List<Intf>>> getMap();
  }

  interface HasList {
    List<Intf> getList();

    void setList(List<Intf> list);
  }

  interface HasMoreChainedSetters extends HasChainedSetters {
    boolean isBoolean();

    HasMoreChainedSetters setBoolean(boolean value);

    @Override
    HasMoreChainedSetters setInt(int value);
  }

  interface Intf {
    int getInt();

    String getProperty();

    String getString();

    void setInt(int number);

    // Avoid name conflicts in AbstractAutoBean
    void setProperty(String value);

    void setString(String value);
  }

  interface OtherIntf {
    HasBoolean getHasBoolean();

    Intf getIntf();

    UnreferencedInFactory getUnreferenced();

    void setHasBoolean(HasBoolean value);

    void setIntf(Intf intf);
  }

  static class RealIntf implements Intf {
    int i;
    String property;
    String string;

    @Override
    public boolean equals(Object o) {
      return (o instanceof Intf) && (((Intf) o).getInt() == getInt());
    }

    @Override
    public int getInt() {
      return i;
    }

    @Override
    public String getProperty() {
      return property;
    }

    @Override
    public String getString() {
      return string;
    }

    @Override
    public int hashCode() {
      return i;
    }

    @Override
    public void setInt(int number) {
      this.i = number;
    }

    @Override
    public void setProperty(String value) {
      this.property = value;
    }

    @Override
    public void setString(String value) {
      this.string = value;
    }

    @Override
    public String toString() {
      return "toString";
    }
  }

  interface UnreferencedInFactory {
  }

  private static class ParameterizationTester extends ParameterizationVisitor {
    private final StringBuilder sb;
    private Stack<Boolean> isOpen = new Stack<Boolean>();

    private ParameterizationTester(StringBuilder sb) {
      this.sb = sb;
    }

    @Override
    public void endVisitType(Class<?> type) {
      if (isOpen.pop()) {
        sb.append(">");
      }
    }

    @Override
    public boolean visitParameter() {
      if (isOpen.peek()) {
        sb.append(",");
      } else {
        sb.append("<");
        isOpen.pop();
        isOpen.push(true);
      }
      return true;
    }

    @Override
    public boolean visitType(Class<?> type) {
      sb.append(type.getName());
      isOpen.push(false);
      return true;
    }
  }

  protected Factory factory;

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

  public void testBooleanIsHasMethods() {
    HasBoolean b = factory.hasBoolean().as();
    assertFalse(b.getGet());
    assertFalse(b.hasHas());
    assertFalse(b.isIs());

    b.setGet(true);
    b.setHas(true);
    b.setIs(true);

    assertTrue(b.getGet());
    assertTrue(b.hasHas());
    assertTrue(b.isIs());
  }

  public void testCategory() {
    AutoBean<HasCall> call = factory.hasCall();
    call.setTag("offset", 1);
    assertEquals(6, call.as().add(2, 3));
    assertEquals(6, CallImpl.seen);
  }

  public void testChainedSetters() {
    AutoBean<HasChainedSetters> bean = factory.hasChainedSetters();
    bean.as().setInt(42).setString("Blah");
    assertEquals(42, bean.as().getInt());
    assertEquals("Blah", bean.as().getString());

    AutoBean<HasMoreChainedSetters> more = factory.hasMoreChainedSetters();
    more.as().setInt(42).setBoolean(true).setString("Blah");
    assertEquals(42, more.as().getInt());
    assertTrue(more.as().isBoolean());
    assertEquals("Blah", more.as().getString());
  }

  public void testDiff() {
    AutoBean<Intf> a1 = factory.intf();
    AutoBean<Intf> a2 = factory.intf();

    assertTrue(AutoBeanUtils.diff(a1, a2).isEmpty());

    a2.as().setInt(42);
    Map<String, Object> diff = AutoBeanUtils.diff(a1, a2);
    assertEquals(1, diff.size());
    assertEquals(42, diff.get("int"));
  }

  public void testDiffWithListPropertyAssignment() {
    AutoBean<HasList> a1 = factory.hasList();
    AutoBean<HasList> a2 = factory.hasList();

    assertTrue(AutoBeanUtils.diff(a1, a2).isEmpty());

    List<Intf> l1 = new ArrayList<Intf>();
    a1.as().setList(l1);
    List<Intf> l2 = new ArrayList<Intf>();
    a2.as().setList(l2);

    assertTrue(AutoBeanUtils.diff(a1, a2).isEmpty());

    l2.add(factory.intf().as());
    Map<String, Object> diff = AutoBeanUtils.diff(a1, a2);
    assertEquals(1, diff.size());
    assertEquals(l2, diff.get("list"));

    l1.add(l2.get(0));
    assertTrue(AutoBeanUtils.diff(a1, a2).isEmpty());
  }

  public void testDynamicMethods() {
    AutoBean<Intf> intf = factory.create(Intf.class);
    assertNotNull(intf);

    RealIntf real = new RealIntf();
    real.i = 42;
    intf = factory.create(Intf.class, real);
    assertNotNull(intf);
    assertEquals(42, intf.as().getInt());
  }

  public void testEquality() {
    AutoBean<Intf> a1 = factory.intf();
    AutoBean<Intf> a2 = factory.intf();

    assertNotSame(a1, a2);
    assertFalse(a1.equals(a2));

    // Make sure as() is stable
    assertSame(a1.as(), a1.as());
    assertEquals(a1.as(), a1.as());

    // When wrapping, use underlying object's equality
    RealIntf real = new RealIntf();
    real.i = 42;
    AutoBean<Intf> w = factory.intf(real);
    // AutoBean interface never equals wrapped object
    assertFalse(w.equals(real));
    // Wrapper interface should delegate hashCode(), equals(), and toString()
    assertEquals(real.hashCode(), w.as().hashCode());
    assertEquals(real, w.as());
    assertEquals(real.toString(), w.as().toString());
    assertEquals(w.as(), real);
  }

  public void testFactory() {
    AutoBean<Intf> auto = factory.intf();
    assertSame(factory, auto.getFactory());
  }

  public void testFreezing() {
    AutoBean<Intf> auto = factory.intf();
    Intf intf = auto.as();
    intf.setInt(42);
    auto.setFrozen(true);
    try {
      intf.setInt(55);
      fail("Should have thrown an exception");
    } catch (IllegalStateException expected) {
    }

    assertTrue(auto.isFrozen());
    assertEquals(42, intf.getInt());
  }

  public void testNested() {
    AutoBean<OtherIntf> auto = factory.otherIntf();
    OtherIntf other = auto.as();

    assertNull(other.getIntf());

    Intf intf = new RealIntf();
    intf.setString("Hello world!");
    other.setIntf(intf);
    Intf retrieved = other.getIntf();
    assertEquals("Hello world!", retrieved.getString());
    assertNotNull(AutoBeanUtils.getAutoBean(retrieved));
  }

  public void testParameterizationVisitor() {
    AutoBean<HasComplexTypes> auto = factory.hasListOfList();
    auto.accept(new AutoBeanVisitor() {
      int count = 0;

      @Override
      public void endVisit(AutoBean<?> bean, Context ctx) {
        assertEquals(3, count);
      }

      @Override
      public void endVisitCollectionProperty(String propertyName, AutoBean<Collection<?>> value,
          CollectionPropertyContext ctx) {
        check(propertyName, ctx);
      }

      @Override
      public void endVisitMapProperty(String propertyName, AutoBean<Map<?, ?>> value,
          MapPropertyContext ctx) {
        check(propertyName, ctx);
      }

      private void check(String propertyName, PropertyContext ctx) {
        count++;
        StringBuilder sb = new StringBuilder();
        ctx.accept(new ParameterizationTester(sb));

        if ("list".equals(propertyName)) {
          // List<List<Intf>>
          assertEquals(List.class.getName() + "<" + List.class.getName() + "<"
              + Intf.class.getName() + ">>", sb.toString());
        } else if ("listOfMap".equals(propertyName)) {
          // List<Map<String, Intf>>
          assertEquals(List.class.getName() + "<" + Map.class.getName() + "<"
              + String.class.getName() + "," + Intf.class.getName() + ">>", sb.toString());
        } else if ("map".equals(propertyName)) {
          // Map<Map<String, String>, List<List<Intf>>>
          assertEquals(Map.class.getName() + "<" + Map.class.getName() + "<"
              + String.class.getName() + "," + String.class.getName() + ">," + List.class.getName()
              + "<" + List.class.getName() + "<" + Intf.class.getName() + ">>>", sb.toString());
        } else {
          throw new RuntimeException(propertyName);
        }
      }
    });
  }

  /**
   * Make sure primitive properties can be returned.
   */
  public void testPrimitiveProperty() {
    AutoBean<Intf> auto = factory.intf();
    Intf intf = auto.as();

    assertNull(intf.getString());
    intf.setString("Hello world!");
    assertEquals("Hello world!", intf.getString());

    assertEquals(0, intf.getInt());
    intf.setInt(42);
    assertEquals(42, intf.getInt());
  }

  public void testTags() {
    AutoBean<Intf> auto = factory.intf();
    auto.setTag("test", 42);
    assertEquals(42, (int) auto.<Integer>getTag("test"));
  }

  public void testTraversal() {
    final AutoBean<OtherIntf> other = factory.otherIntf();
    final AutoBean<Intf> intf = factory.intf();
    final AutoBean<HasBoolean> hasBoolean = factory.hasBoolean();
    other.as().setIntf(intf.as());
    other.as().setHasBoolean(hasBoolean.as());
    intf.as().setInt(42);
    hasBoolean.as().setGet(true);
    hasBoolean.as().setHas(true);
    hasBoolean.as().setIs(true);

    class Checker extends AutoBeanVisitor {
      boolean seenHasBoolean;
      boolean seenIntf;
      boolean seenOther;

      @Override
      public void endVisitReferenceProperty(String propertyName, AutoBean<?> value,
          PropertyContext ctx) {
        if ("hasBoolean".equals(propertyName)) {
          assertSame(hasBoolean, value);
          assertEquals(HasBoolean.class, ctx.getType());
        } else if ("intf".equals(propertyName)) {
          assertSame(intf, value);
          assertEquals(Intf.class, ctx.getType());
        } else if ("unreferenced".equals(propertyName)) {
          assertNull(value);
          assertEquals(UnreferencedInFactory.class, ctx.getType());
        } else {
          fail("Unexpecetd property " + propertyName);
        }
      }

      @Override
      public void endVisitValueProperty(String propertyName, Object value, PropertyContext ctx) {
        if ("int".equals(propertyName)) {
          assertEquals(42, value);
          assertEquals(int.class, ctx.getType());
        } else if ("string".equals(propertyName) || "property".equals(propertyName)) {
          assertNull(value);
          assertEquals(String.class, ctx.getType());
        } else if ("get".equals(propertyName) || "has".equals(propertyName)
            || "is".equals(propertyName)) {
          assertEquals(boolean.class, ctx.getType());
          assertTrue((Boolean) value);
        } else {
          fail("Unknown value property " + propertyName);
        }
      }

      @Override
      public boolean visit(AutoBean<?> bean, Context ctx) {
        if (bean == hasBoolean) {
          seenHasBoolean = true;
        } else if (bean == intf) {
          seenIntf = true;
        } else if (bean == other) {
          seenOther = true;
        } else {
          fail("Unknown AutoBean");
        }
        return true;
      }

      void check() {
        assertTrue(seenHasBoolean);
        assertTrue(seenIntf);
        assertTrue(seenOther);
      }
    }
    Checker c = new Checker();
    other.accept(c);
    c.check();
  }

  public void testType() {
    assertEquals(Intf.class, factory.intf().getType());
  }

  /**
   * Ensure that a totally automatic bean can't be unwrapped, since the
   * generated mapper depends on the AutoBean.
   */
  public void testUnwrappingSimpleBean() {
    AutoBean<Intf> auto = factory.intf();
    try {
      auto.unwrap();
      fail();
    } catch (IllegalStateException expected) {
    }
  }

  public void testWrapped() {
    RealIntf real = new RealIntf();
    AutoBean<Intf> auto = factory.intf(real);
    Intf intf = auto.as();

    assertNotSame(real, intf);
    assertNull(intf.getString());
    assertEquals(0, intf.getInt());

    real.string = "blah";
    assertEquals("blah", intf.getString());
    real.i = 42;
    assertEquals(42, intf.getInt());

    intf.setString("bar");
    assertEquals("bar", real.string);

    intf.setInt(41);
    assertEquals(41, real.i);

    AutoBean<Intf> rewrapped = factory.intf(real);
    assertSame(auto, rewrapped);

    // Disconnect the wrapper, make sure it shuts down correctly.
    Intf unwrapped = auto.unwrap();
    assertSame(real, unwrapped);
    assertNull(AutoBeanUtils.getAutoBean(real));
    try {
      intf.setInt(42);
      fail("Should have thrown exception");
    } catch (IllegalStateException expected) {
    }
  }

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